diff options
-rw-r--r-- | LICENSE | 339 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | asmmon.c | 932 | ||||
-rw-r--r-- | opcode.h | 657 | ||||
-rw-r--r-- | programs/forg.s | 17 | ||||
-rw-r--r-- | programs/hex-to-bcd.s | 7 | ||||
-rw-r--r-- | programs/subasm.s | 296 | ||||
-rw-r--r-- | sux.c | 1230 | ||||
-rw-r--r-- | test/asr.s | 6 | ||||
-rw-r--r-- | test/fib2.s | 26 | ||||
-rw-r--r-- | test/ind-addr.s | 27 | ||||
-rw-r--r-- | test/input.s | 195 | ||||
-rw-r--r-- | test/test-stack.s | 3 | ||||
-rw-r--r-- | test/the-tests.s | 35 |
14 files changed, 2293 insertions, 1480 deletions
@@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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. + + <signature of Ty Coon>, 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 Lesser General +Public License instead of this License. @@ -10,7 +10,8 @@ endif CFLAGS = $(PCC_CFLAGS) $(CFLAGS_EXTRA) OBJS = asmmon.o sux.o OBJ_NAME = cisc-0.2 -all : $(OBJS) +all : clean $(OBJ_NAME) +cisc-0.2: $(OBJS) $(CC) $(OBJS) $(CFLAGS) -lpthread -lcurses -o $(OBJ_NAME) sux.o : $(CC) sux.c -c $(CFLAGS) -o sux.o @@ -4,7 +4,6 @@ #define debug 1 -#define OPNUM 93 #define SETOP(num, _mne, _IMM, _ZM, _ZMX, _ZMY, _IND, _INX, _INY, _ABS, _IMPL) \ {opcodes[num].mnemonic[3] = '\0'; strncpy(opcodes[num].mnemonic, _mne, 3); \ opcodes[num].imm = _IMM; \ @@ -60,19 +59,6 @@ uint64_t use_label(const char *name, uint64_t adr) { struct label *l = mklabel(name, 0, 0); adr++; if (l->def) { - addr[adr] = l->adr & 0xFF; - if (l->adr & 0xFF00) - addr[adr+1] = l->adr >> 8; - if (l->adr & 0xFF000000) { - addr[adr+2] = l->adr >> 16; - addr[adr+3] = l->adr >> 24; - } - if (l->adr & 0xFF00000000000000) { - addr[adr+4] = l->adr >> 32; - addr[adr+5] = l->adr >> 40; - addr[adr+6] = l->adr >> 48; - addr[adr+7] = l->adr >> 56; - } return l->adr; } else { printf("oof, label %s, does not exist, yet.\n", name); @@ -124,102 +110,201 @@ void viewmem(uint64_t address) { printf("\n"); } } + +void usage() { + puts("SuBAsm for CISC-0.2"); + puts("Commands:"); + puts("\tviewmem, vm, v\t\tGet the contents of memory\n" + "\t\t\t\t(Displays 256 bytes of memory\n" + "\t\t\t\t starting from where the program counter\n" + "\t\t\t\t currently is)."); + puts("\trelsv, rf, r\t\tResolve any currently unknown labels."); + puts("\tdisasm, dis,\n" + "\td [start-][end]\t\tDisassemble from starting address, to\n" + "\t\t\t\tending address."); + puts("\tinst, i [inst]\t\tGet a descriptions of that instruction.\n" + "\t\t\t\tIf no argument is specified, or the\n" + "\t\t\t\targument specified is \"all\", list all\n" + "\t\t\t\tinstructions, along with a description\n" + "\t\t\t\tfor each of them."); + puts("\tquit, q\t\t\tQuit the emulator."); + puts("\thelp, h\t\t\tDisplays this mesage."); +} + +void instinfo(const char *inst) { + for(int i = 0; i < OPNUM; i++) { + if (!strcasecmp(inst, mne[i])) { + printf("%s\t%s\n", mne[i], instdesc[i]); + break; + } else if (!strcasecmp(inst, "all")) { + printf("%s\t%s\n", mne[i], instdesc[i]); + } + } +} + +void disasm(uint8_t prefix, uint8_t opcode, uint64_t value) { + char postfix[3]; + char op[4]; + uint8_t addrsize = (prefix & 8) >> 3; + uint8_t rs = (prefix & 0x30) >> 4; + uint8_t regsize = (1 << rs); + op[0] = opname[opcode][0]; + op[1] = opname[opcode][1]; + op[2] = opname[opcode][2]; + op[3] = '\0'; + if (regsize == 1) { + postfix[0] = '\0'; + postfix[1] = '\0'; + postfix[2] = '\0'; + } else { + postfix[0] = '.'; + if (regsize == 2) + postfix[1] = 'W'; + else if (regsize == 4) + postfix[1] = 'D'; + else if (regsize == 8) + postfix[1] = 'Q'; + else { + postfix[0] = '\0'; + postfix[1] = '\0'; + } + postfix[2] = '\0'; + } + switch (optype[opcode]) { + case IMPL: + printf("%s\n" , opname[opcode]); + break; + case IMM: + if (regsize == 1) + printf("%s #$%02x\n" , op, value); + if (regsize == 2) + printf("%s%s #$%04x\n" , op, postfix, value); + if (regsize == 4) + printf("%s%s #$%08x\n" , op, postfix, value); + if (regsize == 8) + printf("%s%s #$%016llx\n" , op, postfix, value); + break; + case ZM: + case ZMX: + case ZMY: + if (addrsize) + printf("%s%s $%08x%s\n" , op, postfix, value, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); + else + printf("%s%s $%02x%s\n" , op, postfix, value, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); + break; + case IND: + case INDX: + case INDY: + if (addrsize) + printf("%s%s ($%08x%s\n" , op, postfix, value, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); + else + printf("%s%s ($%02x%s\n" , op, postfix, value, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); + break; + case ABS: + if (addrsize) + printf("%s%s $%016llx\n" , op, postfix, value); + else + printf("%s%s $%04x\n" , op, postfix, value); + break; + + } +} + int asmmon(const char *fn) { - opent opcodes[OPNUM]; /* mne IMM ZM ZMX ZMY IND INX INY ABS IMPL*/ SETOP( 0, "CPS", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); SETOP( 1, "ADC", 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00); SETOP( 2, "AAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02); - SETOP( 3, "PHB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06); - SETOP( 4, "PHP", 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP( 5, "PHA", 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP( 6, "PHY", 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP( 7, "TAY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B); - SETOP( 8, "PHX", 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP( 9, "TAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D); - SETOP(10, "TYX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E); - SETOP(11, "JMP", 0x00, 0xD0, 0x00, 0x00, 0x04, 0x14, 0x24, 0x10, 0x00); - SETOP(12, "SBC", 0x11, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00); - SETOP(13, "SAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12); - SETOP(14, "PLB", 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(15, "PLP", 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(16, "PLA", 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(17, "PLY", 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(18, "TYA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B); - SETOP(19, "PLX", 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(20, "TXA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D); - SETOP(21, "TXY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E); - SETOP(22, "JSR", 0x00, 0x20, 0x00, 0x00, 0x34, 0x44, 0x54, 0x00, 0x00); - SETOP(23, "AND", 0x21, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00); - SETOP(24, "ABA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22); - SETOP(25, "STT", 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(26, "TAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26); - SETOP(27, "TSX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E); - SETOP(28, "BPO", 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00); - SETOP(29, "ORA", 0x31, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00); - SETOP(30, "OAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32); - SETOP(31, "TBA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36); - SETOP(32, "SEI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38); - SETOP(33, "TXS", 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(34, "BNG", 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00); - SETOP(35, "XOR", 0x41, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00); - SETOP(36, "XAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42); - SETOP(37, "CLI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48); - SETOP(38, "BCS", 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00); - SETOP(39, "LSL", 0x51, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00); - SETOP(40, "LLB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52); - SETOP(41, "STB", 0x00, 0x7F, 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0x5F, 0x00); - SETOP(42, "SEC", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58); - SETOP(43, "STA", 0x00, 0x7B, 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0x5B, 0x00); - SETOP(44, "STY", 0x00, 0x7D, 0x8D, 0x00, 0xAD, 0xBD, 0x00, 0x5D, 0x00); - SETOP(45, "STX", 0x00, 0x7E, 0x00, 0x9E, 0xAE, 0x00, 0xCE, 0x5E, 0x00); - SETOP(46, "BCC", 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00); - SETOP(47, "LSR", 0x61, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00); - SETOP(48, "LRB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62); - SETOP(49, "LDB", 0x66, 0x76, 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0x56, 0x00); - SETOP(50, "CLC", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68); - SETOP(51, "LDA", 0x69, 0x79, 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0x59, 0x00); - SETOP(52, "LDY", 0x6A, 0x7A, 0x8A, 0x00, 0xAA, 0xBA, 0x00, 0x5A, 0x00); - SETOP(53, "LDX", 0x6C, 0x7C, 0x00, 0x9C, 0xAC, 0x00, 0xCC, 0x5C, 0x00); - SETOP(54, "BEQ", 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00); - SETOP(55, "ROL", 0x71, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00); - SETOP(56, "RLB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72); - SETOP(57, "SSP", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78); - SETOP(58, "BNE", 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00); - SETOP(59, "ROR", 0x81, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00); - SETOP(60, "RRB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82); - SETOP(61, "CSP", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88); - SETOP(62, "BVS", 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00); - SETOP(63, "MUL", 0x91, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00); - SETOP(64, "MAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92); - SETOP(65, "SEV", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98); - SETOP(66, "BVC", 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00); - SETOP(67, "DIV", 0xA1, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00); - SETOP(68, "DAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2); - SETOP(69, "CLV", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8); - SETOP(70, "RTS", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0); - SETOP(71, "CMP", 0xB1, 0xB5, 0x00, 0x00, 0xE9, 0xEB, 0xED, 0xB3, 0x00); - SETOP(72, "CAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2); - SETOP(73, "CPY", 0x2A, 0x3B, 0x00, 0x00, 0xEA, 0xFA, 0x00, 0x2B, 0x00); - SETOP(74, "CPX", 0xBC, 0x3D, 0x00, 0x00, 0xEC, 0x00, 0xFC, 0x2D, 0x00); - SETOP(75, "CPB", 0xD6, 0xF6, 0x00, 0x00, 0xDF, 0xEF, 0xFF, 0xE6, 0x00); - SETOP(76, "ENT", 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP( 3, "JMP", 0x00, 0xD0, 0x00, 0x00, 0x04, 0x14, 0x24, 0x10, 0x00); + SETOP( 4, "PHB", 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP( 5, "PHP", 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP( 6, "LDA", 0x09, 0x39, 0x59, 0x79, 0x99, 0xB9, 0xD9, 0x19, 0x00); + SETOP( 7, "LDY", 0x0A, 0x3A, 0x5A, 0x00, 0x7A, 0x9A, 0x00, 0x1A, 0x00); + SETOP( 8, "LDX", 0x0B, 0x3B, 0x00, 0x5B, 0x7B, 0x00, 0x9B, 0x1B, 0x00); + SETOP( 9, "TAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C); + SETOP(10, "LDB", 0x0E, 0x3E, 0x5E, 0x7E, 0x9E, 0xBE, 0xDE, 0x1E, 0x00); + SETOP(11, "SBC", 0x11, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00); + SETOP(12, "SAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12); + SETOP(13, "PLB", 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP(14, "PLP", 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP(15, "TBA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C); + SETOP(16, "JSR", 0x00, 0x20, 0x00, 0x00, 0x34, 0x44, 0x54, 0x00, 0x00); + SETOP(17, "AND", 0x21, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00); + SETOP(18, "ABA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22); + SETOP(19, "CPB", 0x26, 0x46, 0x00, 0x00, 0x56, 0x66, 0x76, 0x36, 0x00); + SETOP(20, "STT", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28); + SETOP(21, "STA", 0x00, 0x49, 0x69, 0x89, 0xA9, 0xC9, 0xE9, 0x29, 0x00); + SETOP(22, "STY", 0x00, 0x4A, 0x6A, 0x00, 0x8A, 0xAA, 0x00, 0x2A, 0x00); + SETOP(23, "STX", 0x00, 0x4B, 0x00, 0x6B, 0x8B, 0x00, 0xAB, 0x2B, 0x00); + SETOP(24, "TAY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C); + SETOP(25, "STB", 0x00, 0x4E, 0x6E, 0x8E, 0xAE, 0xCE, 0xEE, 0x2E, 0x00); + SETOP(26, "BPO", 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00); + SETOP(27, "ORA", 0x31, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00); + SETOP(28, "OAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32); + SETOP(29, "SEI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38); + SETOP(30, "TYA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C); + SETOP(31, "BNG", 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00); + SETOP(32, "XOR", 0x41, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00); + SETOP(33, "XAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42); + SETOP(34, "CLI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48); + SETOP(35, "TAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C); + SETOP(36, "BCS", 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00); + SETOP(37, "LSL", 0x51, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00); + SETOP(38, "LLB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52); + SETOP(39, "SEC", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58); + SETOP(40, "TXA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C); + SETOP(41, "BCC", 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00); + SETOP(42, "LSR", 0x61, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00); + SETOP(43, "LRB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62); + SETOP(44, "CLC", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68); + SETOP(45, "TYX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C); + SETOP(46, "BEQ", 0x00, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00); + SETOP(47, "ROL", 0x71, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00); + SETOP(48, "RLB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72); + SETOP(49, "SSP", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78); + SETOP(50, "TXY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C); + SETOP(51, "BNE", 0x00, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00); + SETOP(52, "ROR", 0x81, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00); + SETOP(53, "RRB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82); + SETOP(54, "INY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86); + SETOP(55, "CSP", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88); + SETOP(56, "TSX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C); + SETOP(57, "BVS", 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00); + SETOP(58, "MUL", 0x91, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00); + SETOP(59, "MAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92); + SETOP(60, "DEY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96); + SETOP(61, "SEV", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98); + SETOP(62, "TXS", 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP(63, "BVC", 0x00, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00); + SETOP(64, "DIV", 0xA1, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00); + SETOP(65, "DAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2); + SETOP(66, "INX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6); + SETOP(67, "CLV", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8); + SETOP(68, "PHY", 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP(69, "RTS", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0); + SETOP(70, "CMP", 0xB1, 0xB5, 0x00, 0x00, 0xF1, 0xF3, 0xF5, 0xB3, 0x00); + SETOP(71, "CAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2); + SETOP(72, "DEX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB6); + SETOP(73, "ENT", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8); + SETOP(74, "CPY", 0xBA, 0xDA, 0x00, 0x00, 0xEA, 0xFA, 0x00, 0xCA, 0x00); + SETOP(75, "CPX", 0xBB, 0xDB, 0x00, 0x00, 0xEB, 0x00, 0xFB, 0xCB, 0x00); + SETOP(76, "PLY", 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); SETOP(77, "RTI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0); SETOP(78, "INC", 0x00, 0xC5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xC1); SETOP(79, "IAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2); - SETOP(80, "INY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A); - SETOP(81, "INX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C); + SETOP(80, "WAI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8); + SETOP(81, "PHX", 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); SETOP(82, "DEC", 0x00, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD3, 0xD1); SETOP(83, "DBA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2); - SETOP(84, "DEY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A); - SETOP(85, "DEX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C); - SETOP(86, "WAI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8); - SETOP(87, "JSL", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00); - SETOP(88, "ASR", 0xE1, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x00); - SETOP(89, "ARB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2); - SETOP(90, "NOP", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8); - SETOP(91, "RTL", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0); - SETOP(92, "BRK", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8); + SETOP(84, "PLX", 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP(85, "JSL", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00); + SETOP(86, "ASR", 0xE1, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x00); + SETOP(87, "ARB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2); + SETOP(88, "NOP", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8); + SETOP(89, "PHA", 0xEC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP(90, "RTL", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0); + SETOP(91, "BRK", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8); + SETOP(92, "PLA", 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); FILE *fp; if (strcasecmp(fn, "stdin") != 0) { fp = fopen(fn, "r"); @@ -228,21 +313,25 @@ int asmmon(const char *fn) { } uint8_t done = 0; uint64_t address = 0x0000; + uint64_t start, end; + uint8_t prefix, opcode; while (!(done & 1)) { char *buf = NULL; char *ins; char *postfix; char mode[3]; opent op; - uint8_t addrmode = 0; + uint8_t addrmode = IMPL; uint64_t value = 0; char *oprand; char *cmd; char ir[2] = ""; /* Index register. */ int a = 0; + int b = 0; char *tmp = malloc(sizeof(char *)*128); size_t size; - done &= ~0x1F; + prefix = 0; + done = 0; if (!strcasecmp(fn, "stdin")) { getline(&buf, &size, stdin); } else { @@ -260,7 +349,7 @@ int asmmon(const char *fn) { if (oprand != NULL) { for (int i = 0; i < strlen(oprand); i++) { if (oprand[i] == '(') - addrmode = 6; + addrmode = IND; if (oprand[i] == '"') break; if (a && oprand[a] == ',') { @@ -272,7 +361,13 @@ int asmmon(const char *fn) { ir[0] = 'y'; ir[1] = '\0'; } + if (b && ir[0] == 'y') + oprand[b] = '\0'; } + if (oprand[i] == ')' && oprand[i+1] == ',') + b = i; + else if (oprand[i] == ')') + oprand[i] = '\0'; if (oprand[i] == ',' || oprand[i] == ';') a = i; } @@ -287,173 +382,327 @@ int asmmon(const char *fn) { done |= 4; viewmem(address); } + if (!strcasecmp(cmd, "reslv") || !strcasecmp(cmd, "rf") || !strcasecmp(cmd, "r")) { + done |= 4; + puts("Resolving unknown labels."); + reslv_fixups(); + puts("Finished resolving unknown labels."); + } + if (!strcasecmp(cmd, "help") || !strcasecmp(cmd, "h")) { + done |= 4; + usage(); + } if (oprand == NULL && ins == NULL && postfix == NULL) { done |= 2; } - if (ins != NULL) { - for (int i = 0; i < strlen(ins); i++) { - if (i && ins[i] == ':') { - ins[i] = '\0'; - mklabel(ins, address, 1); - #if debug - printf("Created label with the name %s, at address: $%llx\n", ins, address); - #endif - done |= 6; - break; - } - if (ins[i] == ';') { - if (i && (ins[i-1] == ' ' || ins[i-1] == '\t')) - ins[i] = '\0'; - else - done |=6; - break; - } - } - if (strcasecmp(ins, ".org") == 0) { - done |= 6; - oprand = strtok(oprand, "$"); - address = strtoull(oprand, NULL, 16); - #if debug - printf("Origin for program code is now at address $%llx.\n", address); - #endif + cmd = strtok(cmd, " \n"); + if (!strcasecmp(cmd, "inst") || !strcasecmp(cmd, "i")) { + done |= 64; + done |= 6; + if (oprand != NULL) { + instinfo(oprand); + } else { + instinfo("all"); } - if (strcasecmp(ins, ".byte") == 0 || strcasecmp(ins, ".word") == 0 || strcasecmp(ins, ".dword") == 0 || strcasecmp(ins, ".qword") == 0) { - done |= 6; - uint8_t qstr = 0; - uint64_t staddr = address; - uint16_t slen = 0; - char *tmpstr = tstr; - char c; - for (int i = 0; i < strlen(oprand); i++) { - if (!qstr) { - if ((isalnum(oprand[i]) || oprand[i] == '_') && oprand[i] != '"') { - qstr = 0; - value = use_label(oprand, address); - sprintf(oprand, "%llx", value); + + } + if (!strcasecmp(cmd, "disasm") || !strcasecmp(cmd, "dis") || !strcasecmp(cmd, "d")) { + done |= 64; + done |= 6; + if (oprand != NULL) { + cmd = strtok_r(oprand, " -", &tmp); + if (cmd != NULL) { + for (int i = 0; i < strlen(cmd); i++) { + if ((isalnum(cmd[i]) || cmd[i] == '_') && cmd[i] != '"') { + value = use_label(tmp, address); + sprintf(tmp, "%llx", value); break; } - if (oprand[i] == '"' && !strcasecmp(ins, ".byte")) { - qstr = 1; - continue; + if (cmd[i] == '$') { + cmd = strtok(cmd, "$"); + value = strtoull(cmd, NULL, 16); + break; } - if (oprand[i] == '$') { - qstr = 0; - oprand = strtok(oprand, "$"); - value = strtoull(oprand, NULL, 16); + if (cmd[i] == ';') { + done |= 16; + break; + } + } + start = value; + for (int i = 0; i < strlen(tmp); i++) { + if ((isalnum(tmp[i]) || tmp[i] == '_') && tmp[i] != '"') { + value = use_label(tmp, address); + sprintf(tmp, "%llx", value); + break; + } + if (tmp[i] == '$') { + tmp = strtok(tmp, "$"); + value = strtoull(tmp, NULL, 16); break; } - if (oprand[i] == ';') { - qstr = 0; + if (tmp[i] == ';') { done |= 16; break; } - } else if (qstr == 1) { - switch (oprand[i]) { - case 0: - puts("oof, unterminated string."); - qstr = 2; - break; - case '"': - value = '\0'; - c = '\0'; - tmpstr[slen++] = '\0'; - qstr = 3; - break; - case '\\': - switch (oprand[i+1]) { - case 'n': - value = '\n'; - c = '\n'; - tmpstr[slen++] = '\\'; - tmpstr[slen++] = 'n'; - break; - case 't': - value = '\t'; - c = '\t'; - tmpstr[slen++] = '\\'; - tmpstr[slen++] = 't'; - break; - case 'r': - value = '\r'; - c = '\r'; - tmpstr[slen++] = '\\'; - tmpstr[slen++] = 'r'; + } + (!strlen(tmp)) ? (end = address) : (end = value); + } else { + start = value; + end = address; + } + } else { + start = 0; + end = address; + } + while (start < end) { + uint8_t rs; + uint8_t regsize; + uint8_t addrsize; + if (start < 0xFF) + printf("$%02llx: ", start); + else if (start < 0xFFFF) + printf("$%04llx: ", start); + else if (start < 0xFFFFFFFF) + printf("$%08llx: ", start); + else if (start < 0xFFFFFFFFFFFFFFFF) + printf("$%016llx: ", start); + prefix = addr[start]; + if ((prefix & 0x07) == 0x07) { + start+=1; + addrsize = (prefix & 8) >> 3; + rs = (prefix & 0x30) >> 4; + regsize = (1 << rs); + } else { + prefix = 0; + regsize = 1; + addrsize = 0; + } + opcode = addr[start]; + start+=1; + switch (optype[opcode]) { + case IMPL: + break; + case IMM: + value = addr[start]; + if (regsize >= 2) + value |= addr[start+1] << 8; + if (regsize >= 4) { + value |= addr[start+2] << 16; + value |= addr[start+3] << 24; + } + if (regsize >= 8) { + value |= (uint64_t)addr[start+4] << 32; + value |= (uint64_t)addr[start+5] << 40; + value |= (uint64_t)addr[start+6] << 48; + value |= (uint64_t)addr[start+7] << 56; + } + start += regsize; + break; + case ZM: + case ZMX: + case ZMY: + case IND: + case INDX: + case INDY: + value = addr[start]; + if (addrsize) { + value |= addr[start+1] << 8; + value |= addr[start+2] << 16; + value |= addr[start+3] << 24; + start+=4; + } else { + start+=1; + } + break; + case ABS: + value = addr[start]; + value |= addr[start+1] << 8; + if (addrsize) { + value |= (uint64_t)addr[start+2] << 16; + value |= (uint64_t)addr[start+3] << 24; + value |= (uint64_t)addr[start+4] << 32; + value |= (uint64_t)addr[start+5] << 40; + value |= (uint64_t)addr[start+6] << 48; + value |= (uint64_t)addr[start+7] << 56; + start+=8; + } else { + start+=2; + } + break; + } + disasm(prefix, opcode, value); + } + } + if (!(done & 64)) { + if (ins != NULL) { + for (int i = 0; i < strlen(ins); i++) { + if (i && ins[i] == ':') { + ins[i] = '\0'; + mklabel(ins, address, 1); + #if debug + printf("Created label with the name %s, at address: $%llx\n", ins, address); + #endif + done |= 6; + break; + } + if (ins[i] == ';') { + if (i && (ins[i-1] == ' ' || ins[i-1] == '\t')) + ins[i] = '\0'; + else + done |=6; + break; + } + } + if (!(done & 6)) { + if (oprand != NULL) { + if (!strcasecmp(ins, ".org")) { + done |= 6; + oprand = strtok(oprand, "$"); + address = strtoull(oprand, NULL, 16); + #if debug + printf("Origin for program code is now at address $%llx.\n", address); + #endif + } + if (!strcasecmp(ins, ".byte") || !strcasecmp(ins, ".word") || !strcasecmp(ins, ".dword") || !strcasecmp(ins, ".qword")) { + done |= 6; + uint8_t qstr = 0; + uint64_t staddr = address; + uint16_t slen = 0; + char *tmpstr = tstr; + char c; + for (int i = 0; i < strlen(oprand); i++) { + if (!qstr) { + if ((isalnum(oprand[i]) || oprand[i] == '_') && oprand[i] != '"') { + qstr = 0; + value = use_label(oprand, address); + sprintf(oprand, "%llx", value); break; - case '0': + } + if (oprand[i] == '"' && !strcasecmp(ins, ".byte")) { + qstr = 1; + continue; + } + if (oprand[i] == '$') { + qstr = 0; + oprand = strtok(oprand, "$"); + value = strtoull(oprand, NULL, 16); break; - default: - value = oprand[i]; - tmpstr[slen++] = '\\'; - tmpstr[slen++] = oprand[i]; + } + if (oprand[i] == ';') { + qstr = 0; + done |= 16; break; + } + } else if (qstr == 1) { + switch (oprand[i]) { + case 0: + puts("oof, unterminated string."); + qstr = 2; + break; + case '"': + value = '\0'; + c = '\0'; + tmpstr[slen++] = '\0'; + qstr = 3; + break; + case '\\': + switch (oprand[i+1]) { + case 'n': + value = '\n'; + c = '\n'; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = 'n'; + break; + case 't': + value = '\t'; + c = '\t'; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = 't'; + break; + case 'r': + value = '\r'; + c = '\r'; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = 'r'; + break; + case '0': + break; + default: + value = oprand[i]; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = oprand[i]; + break; + } + i++; + break; + default: + value = oprand[i]; + c = oprand[i]; + tmpstr[slen++] = c; + break; + } + addr[address++] = (uint8_t)value & 0xFF; } - i++; - break; - default: - value = oprand[i]; - c = oprand[i]; - tmpstr[slen++] = c; - break; + } + if (!strcasecmp(ins, ".byte") && !qstr) + addr[address++] = value & 0xFF; + if (!strcasecmp(ins, ".word")) { + addr[address] = (uint8_t)value & 0xFF; + addr[address+1] = value >> 8; + address+=2; + } + if (!strcasecmp(ins, ".dword")) { + addr[address] = (uint8_t)value & 0xFF; + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + address+=4; + } + if (!strcasecmp(ins, ".qword")) { + addr[address] = (uint8_t)value & 0xFF; + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + addr[address+4] = value >> 32; + addr[address+5] = value >> 40; + addr[address+6] = value >> 48; + addr[address+7] = value >> 56; + address+=8; + } + #if debug + if (!qstr) { + printf("The value $%llx was placed at address%s ", value, (staddr != address-1) ? "es" : ""); + if (staddr == address-1) + printf("$%llx.\n", staddr); + else + printf("$%llx-$%llx.\n", staddr, address-1); + } else { + printf("The string \"%s\", was placed at address%s ", tmpstr, (staddr != address-1) ? "es" : ""); + if (staddr == address-1) + printf("$%llx.\n", staddr); + else + printf("$%llx-$%llx.\n", staddr, address-1); + } + #endif } - addr[address++] = value & 0xFF; } } - if (strcasecmp(ins, ".byte") == 0 && !qstr) - addr[address++] = value & 0xFF; - if (strcasecmp(ins, ".word") == 0) { - addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - address+=2; - } - if (strcasecmp(ins, ".dword") == 0) { - addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - address+=4; - } - if (strcasecmp(ins, ".qword") == 0) { - addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - addr[address+4] = value >> 32; - addr[address+5] = value >> 40; - addr[address+6] = value >> 48; - addr[address+7] = value >> 56; - address+=8; - } - #if debug - if (!qstr) { - printf("The value $%llx was placed at address%s ", value, (staddr != address-1) ? "es" : ""); - if (staddr == address-1) - printf("$%llx.\n", staddr); - else - printf("$%llx-$%llx.\n", staddr, address-1); - } else { - printf("The string \"%s\", was placed at address%s ", tmpstr, (staddr != address-1) ? "es" : ""); - if (staddr == address-1) - printf("$%llx.\n", staddr); - else - printf("$%llx-$%llx.\n", staddr, address-1); - } - #endif } } if (oprand == NULL && !strcasecmp(ins, "TXS")) { - addrmode = 1; + addrmode = IMM; done |= 32; } else if (oprand != NULL && !strcasecmp(ins, "TXS")) - addr[address++] = 0x17; + prefix = 0x17; if (!(done & 2) && oprand != NULL) { mode[0] = oprand[0]; mode[1] = oprand[1]; - if (oprand[0] == '#' || oprand[0] == '$' || oprand[0] == '(') { + if (oprand[0] == '#' || oprand[0] == '$' || (oprand[0] == '(' && (oprand[1] == '$' || oprand[1] == '%'))) { oprand = strtok(oprand, "#($%"); if (mode[0] == '#') { - addrmode = 1; + addrmode = IMM; done |= 32; if (mode[1] == '$') value = strtoull(oprand, NULL, 16); @@ -468,26 +717,33 @@ int asmmon(const char *fn) { value = strtoull(oprand, NULL, 2); else value = strtoull(oprand, NULL, 10); + if (value & 0xFFFFFF00 && (ir[0] == 'x' || ir[0] == 'y')) + prefix |= 0xF; if (mode[0] != '(') { - if (value & 0xFFFFFFFF || !value) { - addrmode = 2; - } else if (value & 0xFFFFFFFF00000000) { - addrmode = 5; + if (value & 0xFFFF0000 || (value <= 0xFF) || + (value & 0xFF00 && address <= 0xFFFF && (ir[0] == 'x' || ir[0] == 'y'))) { + addrmode = ZM; + if (value & 0xFFFFFF00) + prefix |= 0xF; + } else if (value & 0xFFFFFFFF00000000 || (value & 0xFF00 && address <= 0xFFFF)) { + addrmode = ABS; + if (value & 0xFFFFFFFF00000000) + prefix |= 0xF; } } if ((addrmode == 2 || addrmode == 6) && ir != NULL) { switch (ir[0]) { case 'x': - if (addrmode == 2) - addrmode = 3; - else if (addrmode == 6) - addrmode = 7; + if (addrmode == ZM) + addrmode = ZMX; + else if (addrmode == IND) + addrmode = INDX; break; case 'y': - if (addrmode == 2) - addrmode = 4; - else if (addrmode == 6) - addrmode = 8; + if (addrmode == ZM) + addrmode = ZMY; + else if (addrmode == IND) + addrmode = INDY; break; default: done |= 32; @@ -496,6 +752,8 @@ int asmmon(const char *fn) { } } } else { + if (mode[0] == '(') + oprand = strtok(oprand, "#($%"); for (int i = 0; i < strlen(oprand); i++) { if (oprand[i] == ';') { done |= 16; @@ -503,26 +761,33 @@ int asmmon(const char *fn) { } if ((isalnum(oprand[i]) || oprand[i] == '_') && oprand[i] != '"') { value = use_label(oprand, address); + if (value & 0xFFFFFF00 && (ir[0] == 'x' || ir[0] == 'y')) + prefix |= 0xF; if (mode[0] != '(') { - if (value & 0xFFFFFFFF || !value) { - addrmode = 2; - } else if (value & 0xFFFFFFFF00000000) { - addrmode = 5; + if (value & 0xFFFF0000 || (value <= 0xFF) || + (value <= 0xFFFF && address <= 0xFFFF && (ir[0] == 'x' || ir[0] == 'y'))) { + addrmode = ZM; + if (value & 0xFFFFFF00) + prefix |= 0xF; + } else if (value & 0xFFFFFFFF00000000 || (value & 0xFF00 && address <= 0xFFFF)) { + addrmode = ABS; + if (value & 0xFFFFFFFF00000000) + prefix |= 0xF; } } - if ((addrmode == 2 || addrmode == 6) && ir != NULL && a) { + if ((addrmode == ZM || addrmode == IND) && ir != NULL && a) { switch (ir[0]) { case 'x': - if (addrmode == 2) - addrmode = 3; - else if (addrmode == 6) - addrmode = 7; + if (addrmode == ZM) + addrmode = ZMX; + else if (addrmode == IND) + addrmode = INDX; break; case 'y': - if (addrmode == 2) - addrmode = 4; - else if (addrmode == 6) - addrmode = 8; + if (addrmode == ZM) + addrmode = ZMY; + else if (addrmode == IND) + addrmode = INDY; break; default: done |= 32; @@ -539,14 +804,16 @@ int asmmon(const char *fn) { uint8_t i; for (i = 0; i < OPNUM; i++) { if (strcasecmp(opcodes[i].mnemonic, ins) == 0) { - if (addrmode == 0 && (opcodes[i].impl || opcodes[i].impl == CPS)) { + if (addrmode == IMPL && (opcodes[i].impl || opcodes[i].impl == CPS)) { done |= 8; - } else if (addrmode == 1) { + } else if (addrmode == IMM) { switch (opcodes[i].imm) { + case PHB: case PHP: case PHA: case PHY: case PHX: + case PLB: case PLP: case PLA: case PLY: @@ -594,24 +861,27 @@ int asmmon(const char *fn) { } if (postfix != NULL && !(done & 8)) { if (!strcasecmp(postfix, "w") || !strcasecmp(postfix, "2")) { - addr[address++] = 0x17; + prefix |= 0x17; } else if (!strcasecmp(postfix, "d") || !strcasecmp(postfix, "4")) { - addr[address++] = 0x27; + prefix |= 0x27; } else if (!strcasecmp(postfix, "q") || !strcasecmp(postfix, "8")) { - addr[address++] = 0x37; - } else { + prefix |= 0x37; + } else if (!prefix) { done |=8; } - } else if (postfix == NULL && !(done & 8)) { + } else if (postfix == NULL && (!(done & 8) && !prefix)) { done |=8; } uint8_t r; - if (!(done & 8)) - r = addr[address-1]; - else + if (!(done & 8)) { + r = prefix; + addr[address] = prefix; + address += 1; + } else { r = 0; + } switch (addrmode) { - case 0: + case IMPL: if (op.impl || op.impl == CPS) { addr[address++] = op.impl; break; @@ -619,10 +889,10 @@ int asmmon(const char *fn) { fprintf(stderr, "oof, %s requires an operand.\n", op.mnemonic); } break; - case 1: + case IMM: if (op.imm) { - if (addr[address-1] == 0x17 && op.imm == TXS) - r = 0x17; + if ((prefix & 0x30) == 0x10 && op.imm == TXS) + r = prefix; addr[address++] = op.imm; switch (op.imm) { case PHP: @@ -643,7 +913,7 @@ int asmmon(const char *fn) { addr[address++] = value & 0xFF; break; case TXS: - if (r == 0x17) { + if ((r & 0x30) == 0x10) { addr[address] = value & 0xFF; addr[address+2] = value >> 8; address+=2; @@ -670,96 +940,124 @@ int asmmon(const char *fn) { fprintf(stderr, "oof, %s does not use Immediate data.\n", op.mnemonic); } break; - case 2: + case ZM: if (op.zm) { addr[address++] = op.zm; addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - address+=4; + if ((r & 8) == 8) { + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + address+=4; + } else { + address+=1; + } break; } else { fprintf(stderr, "oof, %s does not use Zero Matrix.\n", op.mnemonic); } break; - case 3: + case ZMX: if (op.zmx) { addr[address++] = op.zmx; addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - address+=4; + if ((r & 8) == 8) { + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + address+=4; + } else { + address+=1; + } break; } else { fprintf(stderr, "oof, %s does not use Zero Matrix, indexed with x.\n", op.mnemonic); } break; - case 4: + case ZMY: if (op.zmy) { addr[address++] = op.zmy; addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - address+=4; + if ((r & 8) == 8) { + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + address+=4; + } else { + address+=1; + } break; } else { fprintf(stderr, "oof, %s does not use Zero Matrix, indexed with y.\n", op.mnemonic); } break; - case 5: + case ABS: if (op.abs) { addr[address++] = op.abs; addr[address] = value & 0xFF; addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - addr[address+4] = value >> 32; - addr[address+5] = value >> 40; - addr[address+6] = value >> 48; - addr[address+7] = value >> 56; - address+=8; + if ((r & 8) == 8) { + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + addr[address+4] = value >> 32; + addr[address+5] = value >> 40; + addr[address+6] = value >> 48; + addr[address+7] = value >> 56; + address+=8; + } else { + address+=2; + } break; } else { fprintf(stderr, "oof, %s cannot be an absolute dictator.\n", op.mnemonic); } break; - case 6: + case IND: if (op.ind) { addr[address++] = op.ind; addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - address+=4; + if ((r & 8) == 8) { + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + address+=4; + } else { + address+=1; + } break; } else { fprintf(stderr, "oof, %s cannot use pointers.\n", op.mnemonic); } break; - case 7: + case INDX: if (op.inx) { addr[address++] = op.inx; addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - address+=4; + if ((r & 8) == 8) { + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + address+=4; + } else { + address+=1; + } break; } else { fprintf(stderr, "oof, %s does not use Indexed Indirect.\n", op.mnemonic); } break; - case 8: + case INDY: if (op.iny) { addr[address++] = op.iny; addr[address] = value & 0xFF; - addr[address+1] = value >> 8; - addr[address+2] = value >> 16; - addr[address+3] = value >> 24; - address+=4; + if ((r & 8) == 8) { + addr[address+1] = value >> 8; + addr[address+2] = value >> 16; + addr[address+3] = value >> 24; + address+=4; + } else { + address+=1; + } break; } else { fprintf(stderr, "oof, %s does not use Indirect Indexed.\n", op.mnemonic); @@ -9,94 +9,96 @@ #define AAB 0x02 /* Add Accumulator with carry by B register. */ #define PHB 0x06 /* PusH B register to stack. */ #define PHP 0x08 /* PusH Processor status to stack. */ -#define PHA 0x09 /* PusH Accumulator to stack. */ -#define PHY 0x0A /* PusH Y register to stack. */ -#define TAY 0x0B /* Transfer Accumulator to Y. */ -#define PHX 0x0C /* PusH X register to stack. */ -#define TAX 0x0D /* Transfer Accumulator to X. */ -#define TYX 0x0E /* Transfer Y to X. */ +#define LDA 0x09 /* LoaD Accumulator. */ +#define LDY 0x0A /* LoaD Y register. */ +#define LDX 0x0B /* LoaD X register. */ +#define TAB 0x0C /* Transfer Accumulator to B. */ +#define LDB 0x0E /* LoaD B register. */ #define JMP 0x10 /* JuMP to memory location. */ #define SBC 0x11 /* SuBtract with Carry. */ #define SAB 0x12 /* Subtract Accumulator with carry by B register. */ #define PLB 0x16 /* PuLl B register to stack. */ #define PLP 0x18 /* PuLl Processor status from stack. */ -#define PLA 0x19 /* PuLl Accumulator from stack. */ -#define PLY 0x1A /* PuLl Y register from stack. */ -#define TYA 0x1B /* Transfer Y to Accumulator. */ -#define PLX 0x1C /* PuLl X register from stack. */ -#define TXA 0x1D /* Transfer X to Accumulator. */ -#define TXY 0x1E /* Transfer X to Y. */ +#define TBA 0x1C /* Transfer B to Accumulator. */ #define JSR 0x20 /* Jump to SubRoutine. */ #define AND 0x21 /* bitwise AND with accumulator. */ #define ABA 0x22 /* bitwise And with Accumulator, and B register. */ -#define TAB 0x26 /* Transfer Accumulator to B. */ +#define CPB 0x26 /* ComPare B register. */ #define STT 0x28 /* STart Threads. */ -#define CPY 0x2A /* ComPare Y register. */ -#define CPX 0x2C /* ComPare X register. */ -#define TSX 0x2E /* Transfer Stack pointer to X. */ +#define STA 0x29 /* STore Accumulator. */ +#define STY 0x2A /* STore Y register. */ +#define STX 0x2B /* STore X register. */ +#define TAY 0x2C /* Transfer Accumulator to Y. */ +#define STB 0x2E /* STore B register. */ #define BPO 0x30 /* Branch if POsitive. */ #define ORA 0x31 /* bitwise OR with Accumulator. */ #define OAB 0x32 /* bitwise Or with Accumulator, and B register. */ -#define TBA 0x36 /* Transfer B to Accumulator. */ #define SEI 0x38 /* SEt Interupt flag. */ -#define INY 0x3A /* INcrement Y register. */ -#define INX 0x3C /* INcrement X register. */ -#define TXS 0x3E /* Transfer X to Stack pointer. */ +#define TYA 0x3C /* Transfer Y to Accumulator. */ #define BNG 0x40 /* Branch if NeGative. */ #define XOR 0x41 /* bitwise XOR with accumulator. */ #define XAB 0x42 /* bitwise Xor with Accumulator, and B register. */ #define CLI 0x48 /* CLear Interupt flag. */ -#define DEY 0x4A /* DEcrement Y register. */ -#define DEX 0x4C /* DEcrement X register. */ +#define TAX 0x4C /* Transfer Accumulator to X. */ #define BCS 0x50 /* Branch if Carry Set. */ #define LSL 0x51 /* Logical Shift Left. */ #define LLB 0x52 /* Logical shift Left accumulator by B. */ #define SEC 0x58 /* SEt Carry flag. */ -#define STA 0x5B /* STore Accumulator. */ -#define STY 0x5D /* STore Y register. */ -#define STX 0x5E /* STore X register. */ -#define STB 0x5F /* STore B register. */ +#define TXA 0x5C /* Transfer X to Accumulator. */ #define BCC 0x60 /* Branch if Carry Clear. */ #define LSR 0x61 /* Logical Shift Right. */ #define LRB 0x62 /* Logical shift Right accumulator by B. */ -#define LDB 0x66 /* LoaD B register. */ #define CLC 0x68 /* CLear Carry flag. */ -#define LDA 0x69 /* LoaD Accumulator. */ -#define LDY 0x6A /* LoaD Y register. */ -#define LDX 0x6C /* LoaD X register. */ +#define TYX 0x6C /* Transfer Y to X. */ #define BEQ 0x70 /* Branch if EQual. */ #define ROL 0x71 /* ROtate Left. */ #define RLB 0x72 /* Rotate Left accumulator by B. */ #define SSP 0x78 /* Set Stack Protection flag. */ +#define TXY 0x7C /* Transfer X to Y. */ #define BNE 0x80 /* Branch if Not Equal. */ #define ROR 0x81 /* ROtate Right. */ #define RRB 0x82 /* Rotate Right accumulator by B. */ +#define INY 0x86 /* INcrement Y register. */ #define CSP 0x88 /* Clear Stack Protection flag. */ +#define TSX 0x8C /* Transfer Stack pointer to X. */ #define BVS 0x90 /* Branch if oVerflow Set. */ #define MUL 0x91 /* MULtiply accumulator. */ #define MAB 0x92 /* Multiply Accumulator by B. */ +#define DEY 0x96 /* DEcrement Y register. */ #define SEV 0x98 /* SEt oVerflow flag. */ +#define TXS 0x9C /* Transfer X to Stack pointer. */ #define BVC 0xA0 /* Branch if oVerflow Clear. */ #define DIV 0xA1 /* DIVide with accumulator. */ #define DAB 0xA2 /* Divide Accumulator by B. */ +#define INX 0xA6 /* INcrement X register. */ #define CLV 0xA8 /* CLear oVerflow flag. */ +#define PHY 0xAC /* PusH Y register to stack. */ #define RTS 0xB0 /* ReTurn from Subroutine. */ #define CMP 0xB1 /* CoMPare accumulator. */ #define CAB 0xB2 /* Compare Accumulator, and B. */ +#define DEX 0xB6 /* DEcrement X register. */ #define ENT 0xB8 /* ENd Threads. */ +#define CPY 0xBA /* ComPare Y register. */ +#define CPX 0xBB /* ComPare X register. */ +#define PLY 0xBC /* PuLl Y register from stack. */ #define RTI 0xC0 /* ReTurn from Interrupt. */ #define INC 0xC1 /* INCrement accumulator. */ #define IAB 0xC2 /* Increment Accumulator, and B register. */ +#define WAI 0xC8 /* WAit for Interrupt. */ +#define PHX 0xCC /* PusH X register to stack. */ #define DEC 0xD1 /* DECrement accumulator. */ #define DBA 0xD2 /* Decrement Accumulator, and B register. */ -#define CPB 0xD6 /* ComPare B register. */ -#define WAI 0xD8 /* WAit for Interrupt. */ +#define PLX 0xDC /* PuLl X register from stack. */ #define JSL 0xE0 /* Jump to Subroutine Long. */ #define ASR 0xE1 /* Arithmetic Shift Right. */ #define ARB 0xE2 /* Arithmetic shift Right accumulator by B. */ #define NOP 0xE8 /* No OPeration. */ +#define PHA 0xEC /* PusH Accumulator to stack. */ #define RTL 0xF0 /* ReTurn from subroutine Long. */ #define BRK 0xF8 /* BReaK. */ +#define PLA 0xFC /* PuLl Accumulator from stack. */ + +#define OPNUM 93 #define C ((uint64_t)1 << 0) #define Z ((uint64_t)1 << 1) @@ -134,6 +136,403 @@ typedef struct { uint8_t impl; } opent; +opent opcodes[OPNUM]; + +enum {IMPL, IMM, ZM, ZMX, ZMY, ABS, IND, INDX, INDY}; + +static const uint8_t optype[0x100] = { + [0x00] = IMPL, + [0x01] = IMM, + [0x02] = IMPL, + [0x03] = ABS, + [0x04] = IND, + [0x05] = ZM, + [0x06] = IMM, + [0x08] = IMM, + [0x09] = IMM, + [0x0A] = IMM, + [0x0B] = IMM, + [0x0C] = IMPL, + [0x0E] = IMM, + [0x10] = ABS, + [0x11] = IMM, + [0x12] = IMPL, + [0x13] = ABS, + [0x14] = INDX, + [0x15] = ZM, + [0x16] = IMM, + [0x18] = IMM, + [0x19] = ABS, + [0x1A] = ABS, + [0x1B] = ABS, + [0x1C] = IMPL, + [0x1E] = ABS, + [0x20] = ZM, + [0x21] = IMM, + [0x22] = IMPL, + [0x23] = ABS, + [0x24] = INDY, + [0x25] = ZM, + [0x26] = IMM, + [0x28] = IMPL, + [0x29] = ABS, + [0x2A] = ABS, + [0x2B] = ABS, + [0x2C] = IMPL, + [0x2E] = ABS, + [0x30] = ABS, + [0x31] = IMM, + [0x32] = IMPL, + [0x33] = ABS, + [0x34] = IND, + [0x35] = ZM, + [0x36] = ABS, + [0x38] = IMPL, + [0x39] = ZM, + [0x3A] = ZM, + [0x3B] = ZM, + [0x3C] = IMPL, + [0x3E] = ZM, + [0x40] = ABS, + [0x41] = IMM, + [0x42] = IMPL, + [0x43] = ABS, + [0x44] = INDX, + [0x45] = ZM, + [0x46] = ZM, + [0x48] = IMPL, + [0x49] = ZM, + [0x4A] = ZM, + [0x4B] = ZM, + [0x4C] = IMPL, + [0x4E] = ZM, + [0x50] = ABS, + [0x51] = IMM, + [0x52] = IMPL, + [0x53] = ABS, + [0x54] = INDY, + [0x55] = ZM, + [0x56] = IND, + [0x58] = IMPL, + [0x59] = ZMX, + [0x5A] = ZMX, + [0x5B] = ZMY, + [0x5C] = IMPL, + [0x5E] = ZMX, + [0x60] = ABS, + [0x61] = IMM, + [0x62] = IMPL, + [0x63] = ABS, + [0x64] = ZM, + [0x65] = ZM, + [0x66] = INDX, + [0x68] = IMPL, + [0x69] = ZMX, + [0x6A] = ZMX, + [0x6B] = ZMY, + [0x6C] = IMPL, + [0x6E] = ZMX, + [0x70] = ABS, + [0x71] = IMM, + [0x72] = IMPL, + [0x73] = ABS, + [0x74] = ZM, + [0x75] = ZM, + [0x76] = INDY, + [0x78] = IMPL, + [0x79] = ZMY, + [0x7A] = IND, + [0x7B] = IND, + [0x7C] = IMPL, + [0x7E] = ZMY, + [0x80] = ABS, + [0x81] = IMM, + [0x82] = IMPL, + [0x83] = ABS, + [0x84] = ZM, + [0x85] = ZM, + [0x86] = IMPL, + [0x88] = IMPL, + [0x89] = ZMY, + [0x8A] = IND, + [0x8B] = IND, + [0x8C] = IMPL, + [0x8E] = ZMY, + [0x90] = ABS, + [0x91] = IMM, + [0x92] = IMPL, + [0x93] = ABS, + [0x94] = ZM, + [0x95] = ZM, + [0x96] = IMPL, + [0x98] = IMPL, + [0x99] = IND, + [0x9A] = INDX, + [0x9B] = INDY, + [0x9C] = IMM, + [0x9E] = IND, + [0xA0] = ABS, + [0xA1] = IMM, + [0xA2] = IMPL, + [0xA3] = ABS, + [0xA4] = ZM, + [0xA5] = ZM, + [0xA6] = IMPL, + [0xA8] = IMPL, + [0xA9] = IND, + [0xAA] = INDX, + [0xAB] = INDY, + [0xAC] = IMM, + [0xAE] = IND, + [0xB0] = IMPL, + [0xB1] = IMM, + [0xB2] = IMPL, + [0xB3] = ABS, + [0xB4] = ZM, + [0xB5] = ZM, + [0xB6] = IMPL, + [0xB8] = IMPL, + [0xB9] = INDX, + [0xBA] = IMM, + [0xBB] = IMM, + [0xBC] = IMM, + [0xBE] = INDX, + [0xC0] = IMPL, + [0xC1] = IMPL, + [0xC2] = IMPL, + [0xC3] = ABS, + [0xC4] = ZM, + [0xC5] = ZM, + [0xC8] = IMPL, + [0xC9] = INDX, + [0xCA] = ABS, + [0xCB] = ABS, + [0xCC] = IMM, + [0xCE] = INDX, + [0xD0] = ZM, + [0xD1] = IMPL, + [0xD2] = IMPL, + [0xD3] = ABS, + [0xD4] = ZM, + [0xD5] = ZM, + [0xD9] = INDY, + [0xDA] = ZM, + [0xDB] = ZM, + [0xDC] = IMM, + [0xDE] = INDY, + [0xE0] = ABS, + [0xE1] = IMM, + [0xE2] = IMPL, + [0xE3] = ABS, + [0xE5] = ZM, + [0xE8] = IMPL, + [0xE9] = INDY, + [0xEA] = IND, + [0xEB] = IND, + [0xEC] = IMM, + [0xEE] = INDY, + [0xF0] = IMPL, + [0xF1] = IND, + [0xF3] = INDX, + [0xF5] = INDY, + [0xF8] = IMPL, + [0xFA] = INDX, + [0xFB] = INDY, + [0xFC] = IMM +}; + +static const char *mne[OPNUM] = { + [ 0] = "CPS", + [ 1] = "ADC", + [ 2] = "AAB", + [ 3] = "JMP", + [ 4] = "PHB", + [ 5] = "PHP", + [ 6] = "LDA", + [ 7] = "LDY", + [ 8] = "LDX", + [ 9] = "TAB", + [10] = "LDB", + [11] = "SBC", + [12] = "SAB", + [13] = "PLB", + [14] = "PLP", + [15] = "TBA", + [16] = "JSR", + [17] = "AND", + [18] = "ABA", + [19] = "CPB", + [20] = "STT", + [21] = "STA", + [22] = "STY", + [23] = "STX", + [24] = "TAY", + [25] = "STB", + [26] = "BPO", + [27] = "ORA", + [28] = "OAB", + [29] = "SEI", + [30] = "TYA", + [31] = "BNG", + [32] = "XOR", + [33] = "XAB", + [34] = "CLI", + [35] = "TAX", + [36] = "BCS", + [37] = "LSL", + [38] = "LLB", + [39] = "SEC", + [40] = "TXA", + [41] = "BCC", + [42] = "LSR", + [43] = "LRB", + [44] = "CLC", + [45] = "TYX", + [46] = "BEQ", + [47] = "ROL", + [48] = "RLB", + [49] = "SSP", + [50] = "TXY", + [51] = "BNE", + [52] = "ROR", + [53] = "RRB", + [54] = "INY", + [55] = "CSP", + [56] = "TSX", + [57] = "BVS", + [58] = "MUL", + [59] = "MAB", + [60] = "DEY", + [61] = "SEV", + [62] = "TXS", + [63] = "BVC", + [64] = "DIV", + [65] = "DAB", + [66] = "INX", + [67] = "CLV", + [68] = "PHY", + [69] = "RTS", + [70] = "CMP", + [71] = "CAB", + [72] = "DEX", + [73] = "ENT", + [74] = "CPY", + [75] = "CPX", + [76] = "PLY", + [77] = "RTI", + [78] = "INC", + [79] = "IAB", + [80] = "WAI", + [81] = "PHX", + [82] = "DEC", + [83] = "DBA", + [84] = "PLX", + [85] = "JSL", + [86] = "ASR", + [87] = "ARB", + [88] = "NOP", + [89] = "PHA", + [90] = "RTL", + [91] = "BRK", + [92] = "PLA" +}; + +static const char *instdesc[OPNUM] = { + [ 0] = "Clears the Processor Status register.", + [ 1] = "ADd accumulator, with operand, Carry if needed.", + [ 2] = "Add Accumulator, with B, carry if needed.", + [ 3] = "JuMP to the address specified.", + [ 4] = "PusH the number of bytes specified, from the B register to the stack.", + [ 5] = "PusH the number of bytes specified, from the Processor status register to the stack.", + [ 6] = "LoaD the value from the operand, to the Accumulator.", + [ 7] = "LoaD the value from the operand, to the Y register.", + [ 8] = "LoaD the value from the operand, to the X register.", + [ 9] = "Transfer the value from the Accumulator, to the B register.", + [10] = "LoaD the value from the operand, to the B register.", + [11] = "SuBtract accumulator, with operand, Carry if needed", + [12] = "Subtract Accumulator, with B, carry if needed.", + [13] = "PuLl the number of bytes specified, from the stack, to the B register.", + [14] = "PuLl the number of bytes specified, from the stack, to the Processor status register.", + [15] = "Transfer the value from the Y register, to the Accumulator.", + [16] = "Jump to a SubRoutine.", + [17] = "Bitwise AND accumulator, with operand.", + [18] = "Bitwise AND Accumulator, with B.", + [19] = "ComPare the B register, with operand.", + [20] = "STart a Thread.", + [21] = "STore the value from the Accumulator, in memory.", + [22] = "STore the value from the Y register, in memory.", + [23] = "STore the value from the X register, in memory.", + [24] = "Transfer the value from the Accumulator, to the Y register.", + [25] = "STore the value from the B register, in memory.", + [26] = "Branch if POsitive.", + [27] = "Bitwise OR Accumulator, with operand.", + [28] = "Bitwise OR Accumulator, with B.", + [29] = "SEt the Interrupt flag.", + [30] = "Transfer the value from the Y register, to the Accumulator.", + [31] = "Branch if NeGative.", + [32] = "Bitwise XOR Accumulator, with operand.", + [33] = "Bitwise XOR Accumulator, with B.", + [34] = "CLear the Interrupt flag.", + [35] = "Transfer the value from the Accumulator, to the X register.", + [36] = "Branch if the Carry flag is Set.", + [37] = "Logical Shift Left accumulator, with operand.", + [38] = "Logical Shift Left accumulator, with B.", + [39] = "SEt the Carry flag.", + [40] = "Transfer the value from the X register, to the Accumulator.", + [41] = "Branch if the Carry flag has been Cleared.", + [42] = "Logical Shift Right accumulator, with operand.", + [43] = "Logical Shift Right accumulator, with B.", + [44] = "CLear the Carry flag.", + [45] = "Transfer the value from the Y register, to the X register.", + [46] = "Branch if EQual (the zero flag has been set).", + [47] = "ROtate Left accumulator, with operand.", + [48] = "Rotate Left accumulator, with B.", + [49] = "Set the Stack Protection flag.", + [50] = "Transfer the value from the X register, to the Y register.", + [51] = "Branch if Not Equal (the zero flag has been cleared).", + [52] = "ROtate Right accumulator, with operand.", + [53] = "Rotate Right accumulator, with B.", + [54] = "INcrement the Y register.", + [55] = "Clear the Stack Protection flag.", + [56] = "Transfer the value from the Stack pointer, to the X register.", + [57] = "Branch if the oVerflow flag is Set.", + [58] = "MULtiply accumulator, with operand.", + [59] = "Multiply Accumulator, with B.", + [60] = "DEcrement the Y register.", + [61] = "SEt the oVerflow flag.", + [62] = "Transfer the value from the X register, to the Stack pointer.", + [63] = "Branch if the oVerflow flag has been Cleared.", + [64] = "DIVide accumulator, with operand, and put the remainder into the B register.", + [65] = "Divide Accumulator, with B, and put the remainder into the X register.", + [66] = "INcrement the X register.", + [67] = "CLear the oVerflow flag.", + [68] = "PusH the number of bytes specified, from the Y register to the stack.", + [69] = "ReTurn from a Subroutine.", + [70] = "CoMPare acumulator, with operand.", + [71] = "Compare Accumulator, with B.", + [72] = "DEcrement the X register.", + [73] = "ENd a Thread.", + [74] = "ComPare the Y register, with operand.", + [75] = "ComPare the X register, with operand.", + [76] = "PuLl the number of bytes specified, from the stack, to the Y register.", + [77] = "ReTurn from an Interrupt.", + [78] = "INCrement accumulator, or memory.", + [79] = "Increment Accumulator, and B.", + [80] = "WAIt for an interrupt.", + [81] = "PusH the number of bytes specified, from the X register to the stack.", + [82] = "DECrement accumulator, or memory.", + [83] = "Decrement Accumulator, and B.", + [84] = "PuLl the number of bytes specified, from the stack, to the X register.", + [85] = "Jump to a Subroutine, Long address.", + [86] = "Arithmetic Shift Right accumulator, with operand.", + [87] = "Arithmetic shift Right accumulator, with B.", + [88] = "NO oPeration.", + [89] = "PusH the number of bytes specified, from the Accumulator to the stack.", + [90] = "ReTurn from subroutine, Long address.", + [91] = "BReaKpoint.", + [92] = "PuLl the number of bytes specified, from the stack, to the Accumulator." +}; + static const char *opname[0x100] = { [0x00] = "CPS", [0x01] = "ADC #", @@ -143,12 +542,11 @@ static const char *opname[0x100] = { [0x05] = "ADC zm", [0x06] = "PHB", [0x08] = "PHP", - [0x09] = "PHA", - [0x0A] = "PHY", - [0x0B] = "TAY", - [0x0C] = "PHX", - [0x0D] = "TAX", - [0x0E] = "TYX", + [0x09] = "LDA #", + [0x0A] = "LDY #", + [0x0B] = "LDX #", + [0x0C] = "TAB", + [0x0E] = "LDB #", [0x10] = "JMP a", [0x11] = "SBC #", [0x12] = "SAB", @@ -157,182 +555,183 @@ static const char *opname[0x100] = { [0x15] = "SBC zm", [0x16] = "PLB", [0x18] = "PLP", - [0x19] = "PLA", - [0x1A] = "PLY", - [0x1B] = "TYA", - [0x1C] = "PLX", - [0x1D] = "TXA", - [0x1E] = "TXY", + [0x19] = "LDA a", + [0x1A] = "LDY a", + [0x1B] = "LDX a", + [0x1C] = "TBA", + [0x1E] = "LDB a", [0x20] = "JSR", [0x21] = "AND #", [0x22] = "ABA", [0x23] = "AND a", [0x24] = "JMP (ind), y", [0x25] = "AND zm", - [0x26] = "TAB", + [0x26] = "CPB #", [0x28] = "STT", - [0x2A] = "CPY #", - [0x2B] = "CPY a", - [0x2C] = "CPX #", - [0x2D] = "CPX a", - [0x2E] = "TSX", - [0x30] = "BPO a", + [0x29] = "STA a", + [0x2A] = "STY a", + [0x2B] = "STX a", + [0x2C] = "TAY", + [0x2E] = "STB a", + [0x30] = "BPO", [0x31] = "ORA #", [0x32] = "OAB", [0x33] = "ORA a", [0x34] = "JSR (ind)", [0x35] = "ORA zm", - [0x36] = "TBA", + [0x36] = "CPB a", [0x38] = "SEI", - [0x3A] = "INY", - [0x3B] = "CPY zm", - [0x3C] = "INX", - [0x3D] = "CPX zm", - [0x3E] = "TXS", - [0x40] = "BNG a", + [0x39] = "LDA zm", + [0x3A] = "LDY zm", + [0x3B] = "LDX zm", + [0x3C] = "TYA", + [0x3E] = "LDB zm", + [0x40] = "BNG", [0x41] = "XOR #", [0x42] = "XAB", [0x43] = "XOR a", [0x44] = "JSR (ind, x)", [0x45] = "XOR zm", + [0x46] = "CPB zm", [0x48] = "CLI", - [0x4A] = "DEY", - [0x4C] = "DEX", - [0x50] = "BCS a", + [0x49] = "STA zm", + [0x4A] = "STY zm", + [0x4B] = "STX zm", + [0x4C] = "TAX", + [0x4E] = "STB zm", + [0x50] = "BCS", [0x51] = "LSL #", [0x52] = "LLB", [0x53] = "LSL a", [0x54] = "JSR (ind), y", [0x55] = "LSL zm", - [0x56] = "LDB a", + [0x56] = "CPB (ind)", [0x58] = "SEC", - [0x59] = "LDA a", - [0x5A] = "LDY a", - [0x5B] = "STA a", - [0x5C] = "LDX a", - [0x5D] = "STY a", - [0x5E] = "STX a", - [0x5F] = "STB a", - [0x60] = "BCC a", + [0x59] = "LDA zm, x", + [0x5A] = "LDY zm, x", + [0x5B] = "LDX zm, y", + [0x5C] = "TXA", + [0x5E] = "LDB zm, x", + [0x60] = "BCC", [0x61] = "LSR #", [0x62] = "LRB", [0x63] = "LSR a", [0x64] = "BPO zm", [0x65] = "LSR zm", - [0x66] = "LDB #", + [0x66] = "CPB (ind, x)", [0x68] = "CLC", - [0x69] = "LDA #", - [0x6A] = "LDY #", - [0x6C] = "LDX #", - [0x70] = "BEQ a", + [0x69] = "STA zm, x", + [0x6A] = "STY zm, x", + [0x6B] = "STX zm, y", + [0x6C] = "TYX", + [0x6E] = "STB zm, x", + [0x70] = "BEQ", [0x71] = "ROL #", [0x72] = "RLB", [0x73] = "ROL a", [0x74] = "BNG zm", [0x75] = "ROL zm", - [0x76] = "LDB zm", + [0x76] = "CPB (ind), y", [0x78] = "SSP", - [0x79] = "LDA zm", - [0x7A] = "LDY zm", - [0x7B] = "STA zm", - [0x7C] = "LDX zm", - [0x7D] = "STY zm", - [0x7E] = "STX zm", - [0x7F] = "STB zm", - [0x80] = "BNE a", + [0x79] = "LDA zm, y", + [0x7A] = "LDY (ind)", + [0x7B] = "LDX (ind)", + [0x7C] = "TXY", + [0x7E] = "LDB zm, y", + [0x80] = "BNE", [0x81] = "ROR #", [0x82] = "RRB", [0x83] = "ROR a", [0x84] = "BCS zm", [0x85] = "ROR zm", - [0x86] = "LDB zm, x", + [0x86] = "INY", [0x88] = "CSP", - [0x89] = "LDA zm, x", - [0x8A] = "LDY zm, x", - [0x8B] = "STA zm, x", - [0x8D] = "STY zm, x", - [0x8F] = "STB zm, x", - [0x90] = "BVS a", + [0x89] = "STA zm, y", + [0x8A] = "STY (ind)", + [0x8B] = "STX (ind)", + [0x8C] = "TSX", + [0x8E] = "STB zm, y", + [0x90] = "BVS", [0x91] = "MUL #", [0x92] = "MAB", [0x93] = "MUL a", [0x94] = "BCC zm", [0x95] = "MUL zm", - [0x96] = "LDB zm, y", + [0x96] = "DEY", [0x98] = "SEV", - [0x99] = "LDA zm, y", - [0x9B] = "STA zm, y", - [0x9C] = "LDX zm, y", - [0x9E] = "STX zm, y", - [0x9F] = "STB zm, y", - [0xA0] = "BVC a", + [0x99] = "LDA (ind)", + [0x9A] = "LDY (ind, x)", + [0x9B] = "LDX (ind), y", + [0x9C] = "TXS", + [0x9E] = "LDB (ind)", + [0xA0] = "BVC", [0xA1] = "DIV #", [0xA2] = "DAB", [0xA3] = "DIV a", [0xA4] = "BEQ zm", [0xA5] = "DIV zm", - [0xA6] = "LDB (ind)", + [0xA6] = "INX", [0xA8] = "CLV", - [0xA9] = "LDA (ind)", - [0xAA] = "LDY (ind)", - [0xAB] = "STA (ind)", - [0xAC] = "LDX (ind)", - [0xAD] = "STY (ind)", - [0xAE] = "STX (ind)", - [0xAF] = "STB (ind)", + [0xA9] = "STA (ind)", + [0xAA] = "STY (ind, x)", + [0xAB] = "STX (ind), y", + [0xAC] = "PHY", + [0xAE] = "STB (ind)", [0xB0] = "RTS", [0xB1] = "CMP #", [0xB2] = "CAB", [0xB3] = "CMP a", [0xB4] = "BNE zm", [0xB5] = "CMP zm", - [0xB6] = "LDB (ind, x)", + [0xB6] = "DEX", [0xB8] = "ENT", [0xB9] = "LDA (ind, x)", - [0xBA] = "LDY (ind, x)", - [0xBB] = "STA (ind, x)", - [0xBD] = "STY (ind, x)", - [0xBF] = "STB (ind, x)", + [0xBA] = "CPY #", + [0xBB] = "CPX #", + [0xBC] = "PLY", + [0xBE] = "LDB (ind, x)", [0xC0] = "RTI", [0xC1] = "INC A", [0xC2] = "IAB", [0xC3] = "INC a", [0xC4] = "BVS zm", [0xC5] = "INC zm", - [0xC6] = "LDB (ind), y", - [0xC9] = "LDA (ind), y", - [0xCB] = "STA (ind), y", - [0xCC] = "LDX (ind), y", - [0xCE] = "STX (ind), y", - [0xCF] = "STB (ind), y", + [0xC8] = "WAI", + [0xC9] = "STA (ind, x)", + [0xCA] = "CPY a", + [0xCB] = "CPX a", + [0xCC] = "PHX", + [0xCE] = "STB (ind, x)", [0xD0] = "JMP zm", [0xD1] = "DEC A", [0xD2] = "DBA", [0xD3] = "DEC a", [0xD4] = "BVC zm", [0xD5] = "DEC zm", - [0xD6] = "CPB #", - [0xD8] = "WAI", - [0xDF] = "CPB (ind)", + [0xD9] = "LDA (ind), y", + [0xDA] = "CPY zm", + [0xDB] = "CPX zm", + [0xDC] = "PLX", + [0xDE] = "LDB (ind), y", [0xE0] = "JSL", [0xE1] = "ASR #", [0xE2] = "ARB", [0xE3] = "ASR a", [0xE5] = "ASR zm", - [0xE6] = "CPB a", [0xE8] = "NOP", - [0xE9] = "CMP (ind)", + [0xE9] = "STA (ind), y", [0xEA] = "CPY (ind)", - [0xEB] = "CMP (ind, x)", - [0xEC] = "CPX (ind)", - [0xED] = "CMP (ind), y", - [0xEF] = "CPB (ind, x)", + [0xEB] = "CPX (ind)", + [0xEC] = "PHA", + [0xEE] = "STB (ind), y", [0xF0] = "RTL", - [0xF6] = "CPB zm", + [0xF1] = "CMP (ind)", + [0xF3] = "CMP (ind, x)", + [0xF5] = "CMP (ind), y", [0xF8] = "BRK", [0xFA] = "CPY (ind, x)", - [0xFC] = "CPX (ind), y", - [0xFF] = "CPB (ind), y" + [0xFB] = "CPX (ind), y", + [0xFC] = "PLA" }; extern int asmmon(); diff --git a/programs/forg.s b/programs/forg.s new file mode 100644 index 0000000..3e6aea1 --- /dev/null +++ b/programs/forg.s @@ -0,0 +1,17 @@ +forg: + iny ; Increment offset. + lda buf, y + jsr iswhite + bcs forg ; Reset y, if we hit the null terminator. + cmp #$2E ; Is this character a '.'? + bne forg_exit ; No, so return. + sty org ; Yes, so store the origin. +forg_end: + iny ; Increment offset. + lda buf, y + jsr istoken + bcs forg_end + dey + sty scr_col +forg_exit: + rts ; End of forg. diff --git a/programs/hex-to-bcd.s b/programs/hex-to-bcd.s new file mode 100644 index 0000000..53a3ff2 --- /dev/null +++ b/programs/hex-to-bcd.s @@ -0,0 +1,7 @@ +hex_to_bcd: + pla #1 ; Get argument. + div #10 ; Divide A by 10. + lsl #4 ; Shift the result left by 4 bits. + oab ; Or the result, with the remainder. + pha #1 ; Push the packed BCD result to the stack. + rts ; Return the result. diff --git a/programs/subasm.s b/programs/subasm.s index ddb7ba2..50f2e8d 100644 --- a/programs/subasm.s +++ b/programs/subasm.s @@ -12,6 +12,111 @@ ver_txt: ver_num: .byte "0.1" +; Directives. +dir: + .byte "org" + .byte "byte" + .byte "word" + .byte "dword" + .byte "qword" + +; Instruction mnemonics. +mne: + .byte "CPS" + .byte "ADC" + .byte "AAB" + .byte "PHB" + .byte "PHP" + .byte "PHA" + .byte "PHY" + .byte "TAY" + .byte "PHX" + .byte "TAX" + .byte "TYX" + .byte "JMP" + .byte "SBC" + .byte "SAB" + .byte "PLB" + .byte "PLP" + .byte "PLA" + .byte "PLY" + .byte "TYA" + .byte "PLX" + .byte "TXA" + .byte "TXY" + .byte "JSR" + .byte "AND" + .byte "ABA" + .byte "STT" + .byte "TAB" + .byte "TSX" + .byte "BPO" + .byte "ORA" + .byte "OAB" + .byte "TBA" + .byte "SEI" + .byte "TXS" + .byte "BNG" + .byte "XOR" + .byte "XAB" + .byte "CLI" + .byte "BCS" + .byte "LSL" + .byte "LLB" + .byte "STB" + .byte "SEC" + .byte "STA" + .byte "STY" + .byte "STX" + .byte "BCC" + .byte "LSR" + .byte "LRB" + .byte "LDB" + .byte "CLC" + .byte "LDA" + .byte "LDY" + .byte "LDX" + .byte "BEQ" + .byte "ROL" + .byte "RLB" + .byte "SSP" + .byte "BNE" + .byte "ROR" + .byte "RRB" + .byte "CSP" + .byte "BVS" + .byte "MUL" + .byte "MAB" + .byte "SEV" + .byte "BVC" + .byte "DIV" + .byte "DAB" + .byte "CLV" + .byte "RTS" + .byte "CMP" + .byte "CAB" + .byte "CPY" + .byte "CPX" + .byte "CPB" + .byte "ENT" + .byte "RTI" + .byte "INC" + .byte "IAB" + .byte "INY" + .byte "INX" + .byte "DEC" + .byte "DBA" + .byte "DEY" + .byte "DEX" + .byte "WAI" + .byte "JSL" + .byte "ASR" + .byte "ARB" + .byte "NOP" + .byte "RTL" + .byte "BRK" + + scr_row: .byte $0 scr_col: @@ -31,6 +136,13 @@ str_buf: .org $2000 buf: +.org $2400 +ptr1: + .qword $2500 + +ptr2: + .qword $2900 + ; Control Register. .org $C000 ctrl_reg: @@ -49,22 +161,22 @@ reset: cps ldx.w #$FFFF txs - ldy #$0 + ldy #0 jsr clr_buf - ldx.w #$0 ; Reset x. - ldy #$0 ; Reset y. + ldx.w #0 ; Reset x. + ldy #0 ; Reset y. jmp print_title read: lda ctrl_reg ; Is the keyboard ready? beq read ; Loop until the keyboard is ready. - lda #$0 ; Start resetting the control register. + lda #0 ; Start resetting the control register. sta ctrl_reg ; Reset the control register. jmp getchar ; We got a key. rset_x: - ldx #$0 ; Reset x. + ldx #0 ; Reset x. stx.w x rts @@ -94,7 +206,7 @@ getline: lda #$A sta scr ; Print newline inc scr_row - lda #$0 + lda #0 sta scr_col inc y jsr rset_x @@ -106,7 +218,7 @@ getchar: beq esc ; Yes, so start getting the escape code. cmp #$A ; Did the user type a newline? beq nl ; Yes, so start parsing the input. - cmp #$8 ; Did the user type a backspace? + cmp #8 ; Did the user type a backspace? beq bs ; Yes, so start checking the buffer. jsr echo ; Print character to screen. @@ -123,16 +235,16 @@ esc: sta c ; Store the escape code, until we need it. jsr isup ; Check if the user pressed up. lda d - cmp #$0 + cmp #0 bne esc_end jsr isdown ; Check if the user pressed down. lda d - cmp #$0 + cmp #0 bne esc_end - lda #$0 + lda #0 jsr isleft ; Check if the user pressed left. lda d - cmp #$0 + cmp #0 bne esc_end jsr isright ; Check if the user pressed right. esc_end: @@ -181,13 +293,13 @@ isleft_done: up: dec scr_row jsr update_pos - lda #$1 + lda #1 sta d jmp isup_done down: inc scr_row jsr update_pos - lda #$1 + lda #1 sta d jmp isdown_done right: @@ -197,7 +309,7 @@ right: left: dec scr_col jsr update_pos - lda #$1 + lda #1 sta d jmp isleft_done @@ -237,47 +349,81 @@ getcol: nl: sta scr ; Print newline. inc scr_row ; Move the cursor down one line. - lda #$0 ; Put a null terminator, in place of the newline. + lda #0 ; Put a null terminator, in place of the newline. sta scr_col ; Move the cursor back to column 0. - sta str_buf, y ; Place it into the input buffer. - ldy.w #$0 ; Reset y, to parse the input. + sta buf, y ; Place it into the input buffer. + ldy.w #0 ; Reset y, to parse the input. jsr parse ; Start parsing input. back: sta scr ; Print backspace. - lda #$0 ; Put a null terminator, in place of the backspace. - sta str_buf, y ; Place it into the input buffer. + lda #0 ; Put a null terminator, in place of the backspace. + sta buf, y ; Place it into the input buffer. dey ; Decrement buffer offset. dec scr_col jmp read ; Get next character. bs: - cpy #$0 ; Are we at the start of the buffer? + cpy #0 ; Are we at the start of the buffer? beq read ; We are, so do not store the backspace into the buffer. jmp back ; We are not, so add the backspace to the buffer. parse: - jmp parse ; Keep printing. - jsr clr_sbuf + jsr getdir + jsr rts -forg: +getdir: iny ; Increment offset. - lda str_buf, y + lda buf, y jsr iswhite - bcs forg ; Reset y, if we hit the null terminator. + bcs getdir ; Reset y, if we hit the null terminator. cmp #$2E ; Is this character a '.'? - bne forg_exit ; No, so return. - sty org ; Yes, so store the origin. -forg_end: + bne getdir_exit ; No, so return. + jsr clr_ptr + +getdir_end: iny ; Increment offset. - lda str_buf, y + lda buf, y + jsr iswhite + bcs getdir_cmp + ora #%00100000 ; Make character lower case. + sta (ptr1), y + jmp getdir_end +gettok: + ply #1 + iny +gettok2: + lda buf, y jsr istoken - bcs forg_end - dey - sty scr_col -forg_exit: - rts ; End of forg. + bcs gettok3 + jmp gettok2 +gettok3: + cmp #$ + cmp #$24 ; Is this character, a '$'? + beq getaddr ; Yes, so start getting the address. + + + +getdir_cmp: + phy #1 + ldy.w #0 + tyx +getdir_cpl: + ldb dir, x ; Start checking if the directive we're using, is "org". + stb (ptr2), y + beq getdir_scmp + inx + iny + jmp getdir_cpl +getdir_scmp: + ldy #0 + jsr strcmp + cpx #0 + beq getdir_tok +getdir_exit: + rts ; End of getdir. + istoken: cmp #$20 ; Is this character a space? @@ -288,7 +434,7 @@ istoken: beq istoken_f ; Yes, so return false. cmp #$3B ; Is this character a ';'? beq istoken_f ; Yes, so return false. - cmp #$0 ; Is this character a null terminator? + cmp #0 ; Is this character a null terminator? beq istoken_f ; Yes, so return false. sec ; Return true. rts ; End of istoken. @@ -299,7 +445,7 @@ istoken_f iswhite: cmp #$20 ; Is this character a space? beq iswhite_t ; Yes, so return true. - cmp #$09 ; Is this character a tab? + cmp #9 ; Is this character a tab? beq iswhite_t ; Yes, so return true. clc ; No, so return false. rts ; End of iswhite. @@ -308,7 +454,7 @@ iswhite_t: rts ; End of iswhite_t. rset_y: - ldy.w #$0 + ldy.w #0 jmp print_buf ; Print the input buffer. print_buf: @@ -325,15 +471,15 @@ spin: jmp spin clr_buf: - lda #$0 - cpy.w #$1000 + lda #0 + cpy.w #$3FF beq clr_end sta buf, y iny jmp clr_buf clr_sbuf: - lda #$0 - cpy.w #$40 + lda #0 + cpy.w #$1FF beq clr_end sta str_buf, y iny @@ -343,7 +489,7 @@ clr_end: rts echo: - sta a + tab ldx scr_col cpx #$4F bne echo_print @@ -351,17 +497,51 @@ echo: beq linewrap linewrap: inc scr_row - ldx #$0 + ldx #0 stx scr_col jsr update_pos echo_print: - lda a + tba sta scr ; Echo typed character. inc scr_col ; Increment the cursor's x coordinate. - sta str_buf, y ; Store typed character into the input buffer. + sta buf, y ; Store typed character into the input buffer. iny ; Increment the buffer offset. rts ; Return. +clr_ptr: + lda #0 + cpy.w #$3FF + beq ptr_end + sta (ptr1), y + sta (ptr2), y + iny + jmp clr_ptr +ptr_end: + rts + +strcmp: + lda (ptr1), y + cmp (ptr2), y + bne strcmp_l1 + tax + beq strcmp_l3 + iny + bne strcmp + jmp strcmp + + +strcmp_l1: + bcs strcmp_l2 + ldx #0 + dex + rts + +strcmp_l2: + ldx #1 +strcmp_l3: + rts + + .org $FFC0 .qword reset @@ -376,9 +556,23 @@ echo_print: .org $FFA0 .qword irq_routine -;.org $0 -;viewmem -;.org $100 -;viewmem -;q -done +.org $0 +v +.org $100 +v +.org $200 +v +.org $300 +v +.org $1000 +v +.org $1100 +v +.org $1200 +v +.org $1300 +v +.org $1400 +v +q + @@ -1,15 +1,16 @@ #include "opcode.h" #include <assert.h> -#include <curses.h> #include <ctype.h> #include <string.h> #include <pthread.h> #define bench 0 -#define debug 1 -#define IO 0 +#define debug 0 +#define IO 1 #define keypoll 0 #if bench #include <sys/time.h> +#else +#include <curses.h> #endif #define THREADS 1 @@ -27,7 +28,9 @@ uint8_t threads_done = 0; uint8_t kbd_rdy = 0; uint8_t wai = 0; uint8_t irq = 0; +#if !bench WINDOW *scr; +#endif pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t main_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; @@ -46,21 +49,26 @@ void *run(void *args) { struct sux *cpu = &thr->sx; uint8_t thread = thr->th; uint64_t address = 0; + uint64_t tmpaddr = 0; uint8_t prefix = 0; uint8_t opcode = 0; uint8_t end = 0; + uint8_t stksize; uint64_t sum = 0; uint64_t value = 0; + uint64_t reg = 0; uint64_t iclk = 0; uint64_t ins = 0; uint64_t sign = 0; char *s = malloc(2048); +#if !bench uint8_t lines = (6*thread)+2; uint8_t bcd[4]; uint8_t idx = 3, iscol = 0; - uint16_t tv = 0xFF50; /* Starting address of the Thread Vectors. */ int x = 0, y = 0; uint8_t esc = 0; +#endif + uint16_t tv = 0xFF50; /* Starting address of the Thread Vectors. */ #if bench gettimeofday(&str[thread], 0); #endif @@ -90,35 +98,229 @@ void *run(void *args) { kbd_rdy &= (uint8_t)~(1 << thread); } prefix = addr[cpu->pc[thread]]; - if ((prefix & 0x0F) == 0x07) + if ((prefix & 0x07) == 0x07) cpu->pc[thread]++; else prefix = 0; opcode = addr[cpu->pc[thread]]; + #if debug && !bench + if (lines > 24*(thread+1)) { + lines = (24*thread)+2; + } #if keypoll pthread_mutex_lock(&mutex); #endif mvwprintw(scr, lines, 0, "pc: $%08llx, a: $%016llx, b: $%016llx, x: $%016llx, y: $%016llx" - ", sp: $%04lx, ps: $%016llx, prefix: $%02x, opcode: $%02x, thread: %u, inst: %s \r" + ", sp: $%04lx, ps: $%016llx, prefix: $%02x, opcode: $%02x, thread: %u, inst: " , cpu->pc[thread], cpu->a[thread], cpu->b[thread], cpu->x[thread], cpu->y[thread] - , cpu->sp[thread], cpu->ps, prefix, opcode, thread, opname[opcode]); - wrefresh(scr); + , cpu->sp[thread], cpu->ps, prefix, opcode, thread); #if keypoll pthread_mutex_unlock(&mutex); #endif - lines++; - if (lines > 24*(thread+1)) - lines = (24*thread)+2; #endif + uint8_t addrsize = (prefix & 8) == 8; uint8_t rs = (prefix & 0x30) >> 4; uint8_t regsize = (1 << rs); uint8_t tmp; address = cpu->pc[thread]; cpu->pc[thread]++; iclk++; + switch (optype[opcode]) { + case IMPL: + break; + case IMM: + switch (opcode) { + case TXS: + case PHB: + case PHP: + case PHA: + case PHY: + case PHX: + case PLB: + case PLP: + case PLA: + case PLY: + case PLX: + break; + case STT: + case LSL: + case LSR: + case ROL: + case ROR: + case ASR: + case ENT: + address = cpu->pc[thread]; + cpu->pc[thread]+=1; + break; + default: + address = cpu->pc[thread]; + cpu->pc[thread]+=regsize; + break; + } + break; + case ZM: + case ZMX: + case ZMY: + address = addr[cpu->pc[thread]]; + if (addrsize) { + address |= addr[cpu->pc[thread]+1] << 8; + address |= addr[cpu->pc[thread]+2] << 16; + address |= addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + } else { + cpu->pc[thread]+=1; + } + tmpaddr = address; + if (optype[opcode] == ZMX) + address += cpu->x[thread]; + if (optype[opcode] == ZMY) + address += cpu->y[thread]; + break; + case IND: + case INDX: + case INDY: + address = addr[cpu->pc[thread]]; + if (addrsize) { + address |= addr[cpu->pc[thread]+1] << 8; + address |= addr[cpu->pc[thread]+2] << 16; + address |= addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + } else { + cpu->pc[thread]+=1; + } + tmpaddr = address; + if (optype[opcode] == INDX) + address += cpu->x[thread]; + value = (uint64_t)addr[address] + | (uint64_t)addr[address+1] << 8 + | (uint64_t)addr[address+2] << 16 + | (uint64_t)addr[address+3] << 24 + | (uint64_t)addr[address+4] << 32 + | (uint64_t)addr[address+5] << 40 + | (uint64_t)addr[address+6] << 48 + | (uint64_t)addr[address+7] << 56; + if (optype[opcode] == INDY) + value += cpu->y[thread]; + address = value; + value = 0; + iclk++; + break; + case ABS: + address = addr[cpu->pc[thread]]; + address |= addr[cpu->pc[thread]+1] << 8; + if (addrsize) { + address |= (uint64_t)addr[cpu->pc[thread]+2] << 16; + address |= (uint64_t)addr[cpu->pc[thread]+3] << 24; + address |= (uint64_t)addr[cpu->pc[thread]+4] << 32; + address |= (uint64_t)addr[cpu->pc[thread]+5] << 40; + address |= (uint64_t)addr[cpu->pc[thread]+6] << 48; + address |= (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } else { + cpu->pc[thread]+=2; + } + + break; + + } + value = addr[address]; + if (regsize >= 2) { + value |= addr[address+1] << 8; + if (regsize >= 4) { + value |= addr[address+2] << 16; + value |= addr[address+3] << 24; + } + if (regsize >= 8) { + value |= (uint64_t)addr[address+4] << 32; + value |= (uint64_t)addr[address+5] << 40; + value |= (uint64_t)addr[address+6] << 48; + value |= (uint64_t)addr[address+7] << 56; + } + } + #if debug && !bench + int row, col; + #if keypoll + pthread_mutex_lock(&mutex); + #endif + getyx(scr,row, col); + char postfix[3]; + char op[4]; + op[0] = opname[opcode][0]; + op[1] = opname[opcode][1]; + op[2] = opname[opcode][2]; + op[3] = '\0'; + if (regsize == 1) { + postfix[0] = '\0'; + postfix[1] = '\0'; + postfix[2] = '\0'; + } else { + postfix[0] = '.'; + if (regsize == 2) + postfix[1] = 'W'; + if (regsize == 4) + postfix[1] = 'D'; + if (regsize == 8) + postfix[1] = 'Q'; + postfix[2] = '\0'; + } + switch (optype[opcode]) { + case IMPL: + mvwprintw(scr, lines, col, "%s \r" , opname[opcode]); + break; + case IMM: + if (regsize == 1) { + mvwprintw(scr, lines, col, "%s #$%02x \r" , op, value); + } + if (regsize == 2) { + mvwprintw(scr, lines, col, "%s%s #$%04x \r" , op, postfix, value); + } + if (regsize == 4) { + mvwprintw(scr, lines, col, "%s%s #$%08x \r" , op, postfix, value); + } + if (regsize == 8) { + mvwprintw(scr, lines, col, "%s%s #$%016llx\r" , op, postfix, value); + } + break; + case ZM: + case ZMX: + case ZMY: + if (optype[opcode] == ZMX) + tmpaddr = address - cpu->x[thread]; + if (optype[opcode] == ZMY) + tmpaddr = address - cpu->y[thread]; + if (addrsize) + mvwprintw(scr, lines, col, "%s%s $%08x%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); + else + mvwprintw(scr, lines, col, "%s%s $%02x%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); + break; + case IND: + case INDX: + case INDY: + if (addrsize) + mvwprintw(scr, lines, col, "%s%s ($%08x%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); + else + mvwprintw(scr, lines, col, "%s%s ($%02x%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); + break; + case ABS: + tmpaddr = address; + if (addrsize) + mvwprintw(scr, lines, col, "%s%s $%016llx\r" , op, postfix, value); + else + mvwprintw(scr, lines, col, "%s%s $%04x \r" , op, postfix, tmpaddr); + break; + + } + mvwprintw(scr, 29, 0, "address: $%016llx\r", address); + wrefresh(scr); + #if keypoll + pthread_mutex_unlock(&mutex); + #endif + lines+=1; + #endif switch(opcode) { case CPS: /* Clear Processor Status. */ for (uint8_t i = 0; i < 8; i++) { @@ -135,48 +337,8 @@ void *run(void *args) { case AAB: /* Add Accumulator with carry by B register. */ case 0x03: /* ADC Absolute. */ case 0x05: /* ADC Zero Matrix. */ - if (opcode != AAB) { - if (opcode == ADC) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } - if (opcode == 0x03) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x05) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - if (regsize >= 2) { - value += (uint64_t)addr[address+1] << 8; - } - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } - } else { + if (opcode == AAB) value = cpu->b[thread]; - } sum = cpu->a[thread]+value+cpu->c[thread]; cpu->a[thread] = sum; cpu->z[thread] = (sum == 0); @@ -305,62 +467,13 @@ void *run(void *args) { } break; case JMP: /* JMP Absolute. */ - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; cpu->pc[thread] = address; break; case SBC: /* SBC Immediate. */ case SAB: /* Subtract Accumulator with carry by B register. */ case 0x13: /* SBC Absolute. */ case 0x15: /* SBC Zero Matrix. */ - if (opcode != SAB) { - if (opcode == SBC) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } - if (opcode == 0x13) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x15) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - if (regsize >= 2) { - value += (uint64_t)addr[address+1] << 8; - } - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } - } else { + if (opcode == SAB) { value = cpu->b[thread]; } sum = cpu->a[thread]-value-!cpu->c[thread]; @@ -438,25 +551,10 @@ void *run(void *args) { case 0x44: /* JSR Indexed Indirect. */ case 0x54: /* JSR Indirect Indexed. */ case JSR: /* Jump to SubRoutine. */ - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24; - if (opcode == 0x34 || opcode == 0x44 || opcode == 0x54) { - address = (uint64_t)addr[address] - | (uint64_t)addr[address+1] << 8 - | (uint64_t)addr[address+2] << 16 - | (uint64_t)addr[address+3] << 24 - | (uint64_t)addr[address+4] << 32 - | (uint64_t)addr[address+5] << 40 - | (uint64_t)addr[address+6] << 48 - | (uint64_t)addr[address+7] << 56; - if (opcode == 0x44) - address += cpu->x[thread]; - if (opcode == 0x54) - address += cpu->y[thread]; - } - cpu->pc[thread]+=4; + if (addrsize) + stksize = 24; + else + stksize = 0; for (int8_t i = 24; i >= 0; i-=8) { if (i) addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> i; @@ -470,44 +568,8 @@ void *run(void *args) { case ABA: /* bitwise And with Accumulator, and B register. */ case 0x23: /* AND Absolute. */ case 0x25: /* AND Zero Matrix. */ - if (opcode != ABA) { - if (opcode == AND) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } - if (opcode == 0x23) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x25) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = (uint64_t)addr[address]; - if (regsize >= 2) - value += (uint64_t)addr[address+1] << 8; - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } + if (opcode == ABA) { + value = cpu->b[thread]; } cpu->a[thread] &= value; cpu->z[thread] = (value == 0); @@ -516,9 +578,6 @@ void *run(void *args) { (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); break; case STT: /* STart Thread. */ - address = cpu->pc[thread]; - cpu->pc[thread]++; - value = addr[address]; cpu->crt |= value; for (uint8_t i = 0; i < 7; i++) { if ((value >> i) & 1) { @@ -536,25 +595,6 @@ void *run(void *args) { break; case BPO: /* BPO Absolute. */ case 0x64: /* BPO Zero Matrix. */ - if (opcode == BPO) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (cpu->n[thread]) cpu->pc[thread] = address; break; @@ -562,45 +602,7 @@ void *run(void *args) { case OAB: /* bitwise Or with Accumulator, and B register. */ case 0x33: /* ORA Absolute. */ case 0x35: /* ORA Zero Matrix. */ - if (opcode != OAB) { - if (opcode == ORA) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } - if (opcode == 0x39) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x3B) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = (uint64_t)addr[address]; - if (regsize >= 2) - value += (uint64_t)addr[address+1] << 8; - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } - } else { + if (opcode == OAB) { value = cpu->b[thread]; } cpu->a[thread] |= value; @@ -615,25 +617,6 @@ void *run(void *args) { break; case BNG: /* BNG Absolute. */ case 0x74: /* BNG Zero Matrix. */ - if (opcode == BNG) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (!cpu->n[thread]) cpu->pc[thread] = address; break; @@ -641,45 +624,7 @@ void *run(void *args) { case XAB: /* bitwise Xor with Accumulator, and B register. */ case 0x43: /* XOR Absolute. */ case 0x45: /* XOR Zero Matrix. */ - if (opcode != XAB) { - if (opcode == XOR) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } - if (opcode == 0x49) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x4B) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = (uint64_t)addr[address]; - if (regsize >= 2) - value += (uint64_t)addr[address+1] << 8; - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } - } else { + if (opcode == XAB) { value = cpu->b[thread]; } cpu->a[thread] ^= value; @@ -694,25 +639,6 @@ void *run(void *args) { break; case BCS: /* BCS Absolute. */ case 0x84: /* BCS Zero Matrix. */ - if (opcode == BCS) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (cpu->c[thread]) cpu->pc[thread] = address; break; @@ -720,34 +646,7 @@ void *run(void *args) { case LLB: /* Logical shift Left accumulator by B. */ case 0x53: /* LSL Absolute. */ case 0x55: /* LSL Zero Matrix. */ - if (opcode != LLB) { - if (opcode == LSL) { - address = cpu->pc[thread]; - cpu->pc[thread]++; - } - if (opcode == 0x53) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x55) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - } else { + if (opcode == LLB) { value = cpu->b[thread]; } sum = (value < 64) ? cpu->a[thread] << value : 0; @@ -767,69 +666,33 @@ void *run(void *args) { case STY: /* STY Absolute. */ case STX: /* STX Absolute. */ case STB: /* STB Absolute. */ - case 0x7B: /* STA Zero Matrix. */ - case 0x7D: /* STY Zero Matrix. */ - case 0x7E: /* STX Zero Matrix. */ - case 0x7F: /* STB Zero Matrix. */ - case 0x8B: /* STA Zero Matrix, Indexed with X. */ - case 0x8D: /* STY Zero Matrix, Indexed with X. */ - case 0x8F: /* STA Zero Matrix, Indexed with X. */ - case 0x9B: /* STA Zero Matrix, Indexed with Y. */ - case 0x9E: /* STX Zero Matrix, Indexed with Y. */ - case 0x9F: /* STA Zero Matrix, Indexed with Y. */ - case 0xAB: /* STA Indirect. */ - case 0xAD: /* STY Indirect. */ - case 0xAE: /* STX Indirect. */ - case 0xAF: /* STB Indirect. */ - case 0xBB: /* STA Indexed Indirect. */ - case 0xBD: /* STY Indexed Indirect. */ - case 0xBF: /* STB Indexed Indirect. */ - case 0xCB: /* STA Indirect Indexed. */ - case 0xCE: /* STX Indirect Indexed. */ - case 0xCF: /* STB Indirect Indexed. */ - if (opcode == STA || opcode == STY || opcode == STX || opcode == STB) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - if (opcode == 0xAB || opcode == 0xAD || opcode == 0xAE || opcode == 0xAF || opcode == 0xBB || - opcode == 0xBD || opcode == 0xBF || opcode == 0xCB || opcode == 0xCE || opcode == 0xCF) { - address = (uint64_t)addr[address] - | (uint64_t)addr[address+1] << 8 - | (uint64_t)addr[address+2] << 16 - | (uint64_t)addr[address+3] << 24 - | (uint64_t)addr[address+4] << 32 - | (uint64_t)addr[address+5] << 40 - | (uint64_t)addr[address+6] << 48 - | (uint64_t)addr[address+7] << 56; - } - if (opcode == 0x8B || opcode == 0x8D || opcode == 0x8F || - opcode == 0xBB || opcode == 0xBD || opcode == 0xBF) - address += cpu->x[thread]; - if (opcode == 0x9B || opcode == 0x9E || opcode == 0x9F || - opcode == 0xCB || opcode == 0xCE || opcode == 0xCF) - address += cpu->y[thread]; - cpu->pc[thread]+=4; - iclk++; - } - if (opcode == STA || opcode == 0x7B || opcode == 0x8B || opcode == 0x9B) + case 0x49: /* STA Zero Matrix. */ + case 0x4A: /* STY Zero Matrix. */ + case 0x4B: /* STX Zero Matrix. */ + case 0x4E: /* STB Zero Matrix. */ + case 0x69: /* STA Zero Matrix, Indexed with X. */ + case 0x6A: /* STY Zero Matrix, Indexed with X. */ + case 0x6B: /* STX Zero Matrix, Indexed with Y. */ + case 0x6E: /* STB Zero Matrix, Indexed with X. */ + case 0x89: /* STA Zero Matrix, Indexed with Y. */ + case 0x8A: /* STY Indirect. */ + case 0x8B: /* STX Indirect. */ + case 0x8E: /* STB Zero Matrix, Indexed with Y. */ + case 0xA9: /* STA Indirect. */ + case 0xAA: /* STY Indexed Indirect. */ + case 0xAB: /* STX Indirect Indexed. */ + case 0xAE: /* STB Indirect. */ + case 0xC9: /* STA Indexed Indirect. */ + case 0xCE: /* STB Indexed Indirect. */ + case 0xE9: /* STA Indirect Indexed. */ + case 0xEE: /* STB Indirect Indexed. */ + if (opcode == STA || opcode == 0x49 || opcode == 0x69 || opcode == 0x89 || opcode == 0xA9 || opcode == 0xC9 || opcode == 0xE9) value = cpu->a[thread]; - if (opcode == STY || opcode == 0x7D || opcode == 0x8D) + if (opcode == STY || opcode == 0x4A || opcode == 0x6A || opcode == 0x8A || opcode == 0xAA) value = cpu->y[thread]; - if (opcode == STX || opcode == 0x7E || opcode == 0x9E) + if (opcode == STY || opcode == 0x4B || opcode == 0x6B || opcode == 0x8B || opcode == 0xAB) value = cpu->x[thread]; - if (opcode == STB || opcode == 0x7F || opcode == 0x8F || opcode == 0x9F) + if (opcode == STB || opcode == 0x4E || opcode == 0x6E || opcode == 0x8E || opcode == 0xAE || opcode == 0xCE || opcode == 0xEE) value = cpu->b[thread]; addr[address] = value & 0xFF; #if IO @@ -923,6 +786,7 @@ void *run(void *args) { #endif } #else + #if !bench if (address == TX_ADDR) { if (esc) { switch(addr[address]) { @@ -955,7 +819,8 @@ void *run(void *args) { x = 0; else x = ((bcd[1]*10) + bcd[0]); - mvwprintw(scr, getmaxy(scr)-25, 0, "x: %i, y: %i ", x, y); + mvwprintw(scr, 30, 0, "x: %i, y: %i ", x, y); + wrefresh(scr); idx = 3; bcd[0] = 0; bcd[1] = 0; @@ -997,6 +862,7 @@ void *run(void *args) { } } #endif + #endif if (regsize >= 2) addr[address+1] = value >> 8; if (regsize >= 4) { @@ -1012,25 +878,6 @@ void *run(void *args) { break; case BCC: /* BCC Absolute. */ case 0x94: /* BCC Zero Matrix. */ - if (opcode == BCC) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (!cpu->c[thread]) cpu->pc[thread] = address; break; @@ -1038,46 +885,26 @@ void *run(void *args) { case LRB: /* Logical shift Right accumulator by B. */ case 0x63: /* LSR Absolute. */ case 0x65: /* LSR Zero Matrix. */ + if (opcode == LRB) { + value = cpu->b[thread]; + } + sum = (value < 64) ? cpu->a[thread] >> value : 0; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + cpu->c[thread] = cpu->a[thread] & 1; + cpu->a[thread] = sum; + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); + break; case ASR: /* ASR Immediate. */ case ARB: /* Arithmetic shift Right accumulator by B. */ case 0xE3: /* ASR Absolute. */ case 0xE5: /* ASR Zero Matrix. */ - if (opcode != LRB || opcode != ARB) { - if (opcode == LSR || opcode == ASR) { - address = cpu->pc[thread]; - cpu->pc[thread]++; - } - if (opcode == 0x63 || opcode == 0xE3) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x65 || opcode == 0xE5) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - } else { + if (opcode == ARB) value = cpu->b[thread]; - } - if (opcode == ASR || opcode == ARB || opcode == 0xE3 || opcode == 0xE5) { - sign = cpu->a[thread] & 0x8000000000000000; - sum = (value < 64) ? (cpu->a[thread] >> value) | sign : 0; - } - if (opcode == LSR || opcode == LRB || opcode == 0x63 || opcode == 0x65) { - sum = (value < 64) ? cpu->a[thread] >> value : 0; - } + sign = cpu->a[thread] & 0x8000000000000000; + sum = (value < 64) ? (cpu->a[thread] >> value) | sign : 0; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->c[thread] = cpu->a[thread] & 1; @@ -1090,73 +917,34 @@ void *run(void *args) { cpu->c[thread] = 0; (cpu->ps &= ~(C << 8*thread)); break; - case 0x56: /* LDB Absolute. */ - case 0x59: /* LDA Absolute. */ - case 0x5A: /* LDY Absolute. */ - case 0x5C: /* LDX Absolute. */ case LDB: /* LDB Immediate. */ case LDA: /* LDA Immediate. */ case LDY: /* LDY Immediate. */ case LDX: /* LDX Immediate. */ - case 0x76: /* LDB Zero Matrix. */ - case 0x79: /* LDA Zero Matrix. */ - case 0x7A: /* LDY Zero Matrix. */ - case 0x7C: /* LDX Zero Matrix. */ - case 0x86: /* LDB Zero Matrix, Indexed with X. */ - case 0x89: /* LDA Zero Matrix, Indexed with X. */ - case 0x8A: /* LDY Zero Matrix, Indexed with X. */ - case 0x96: /* LDB Zero Matrix, Indexed with Y. */ - case 0x99: /* LDA Zero Matrix, Indexed with Y. */ - case 0x9C: /* LDX Zero Matrix, Indexed with Y. */ - case 0xA6: /* LDB Indirect. */ - case 0xA9: /* LDA Indirect. */ - case 0xAA: /* LDY Indirect. */ - case 0xAC: /* LDX Indirect. */ - case 0xB6: /* LDB Indexed Indirect. */ + case 0x1E: /* LDB Absolute. */ + case 0x19: /* LDA Absolute. */ + case 0x1A: /* LDY Absolute. */ + case 0x1B: /* LDX Absolute. */ + case 0x3E: /* LDB Zero Matrix. */ + case 0x39: /* LDA Zero Matrix. */ + case 0x3A: /* LDY Zero Matrix. */ + case 0x3B: /* LDX Zero Matrix. */ + case 0x5E: /* LDB Zero Matrix, Indexed with X. */ + case 0x59: /* LDA Zero Matrix, Indexed with X. */ + case 0x5A: /* LDY Zero Matrix, Indexed with X. */ + case 0x5B: /* LDX Zero Matrix, Indexed with Y. */ + case 0x7E: /* LDB Zero Matrix, Indexed with Y. */ + case 0x79: /* LDA Zero Matrix, Indexed with Y. */ + case 0x7A: /* LDY Indirect. */ + case 0x7B: /* LDX Indirect. */ + case 0x9E: /* LDB Indirect. */ + case 0x99: /* LDA Indirect. */ + case 0x9A: /* LDY Indexed Indirect. */ + case 0x9B: /* LDX Indirect Indexed. */ + case 0xBE: /* LDB Indexed Indirect. */ case 0xB9: /* LDA Indexed Indirect. */ - case 0xBA: /* LDY Indexed Indirect. */ - case 0xC6: /* LDB Indirect Indexed. */ - case 0xC9: /* LDA Indirect Indexed. */ - case 0xCC: /* LDX Indirect Indexed. */ - if (opcode == LDB || opcode == LDA || opcode == LDY || opcode == LDX) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } else if (opcode == 0x56 || opcode == 0x59 || opcode == 0x5A || opcode == 0x5C) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - if (opcode == 0xA6 || opcode == 0xA9 || opcode == 0xAA || opcode == 0xAC || opcode == 0xB6 || - opcode == 0xB9 || opcode == 0xBA || opcode == 0xC6 || opcode == 0xC9 || opcode == 0xCC) { - address = (uint64_t)addr[address] - | (uint64_t)addr[address+1] << 8 - | (uint64_t)addr[address+2] << 16 - | (uint64_t)addr[address+3] << 24 - | (uint64_t)addr[address+4] << 32 - | (uint64_t)addr[address+5] << 40 - | (uint64_t)addr[address+6] << 48 - | (uint64_t)addr[address+7] << 56; - } - if (opcode == 0x86 || opcode == 0x89 || opcode == 0x8A || - opcode == 0xB6 || opcode == 0xB9 || opcode == 0xBA) - address += cpu->x[thread]; - if (opcode == 0x96 || opcode == 0x99 || opcode == 0x9C || - opcode == 0xC6 || opcode == 0xC9 || opcode == 0xCC) - address += cpu->y[thread]; - cpu->pc[thread]+=4; - iclk++; - } + case 0xDE: /* LDB Indirect Indexed. */ + case 0xD9: /* LDA Indirect Indexed. */ if (address == CTRL_ADDR) { pthread_mutex_lock(&main_mutex); pthread_cond_signal(&main_cond); @@ -1180,13 +968,13 @@ void *run(void *args) { value += (uint64_t)addr[address+6] << 48; value += (uint64_t)addr[address+7] << 56; } - if (opcode == LDB || opcode == 0x56 || opcode == 0x76 || opcode == 0x86 || opcode == 0x96) + if (opcode == LDB || opcode == 0x1E || opcode == 0x3E || opcode == 0x5E || opcode == 0x7E || opcode == 0x9E || opcode == 0xBE || opcode == 0xDE) cpu->b[thread] = value; - if (opcode == LDA || opcode == 0x59 || opcode == 0x79 || opcode == 0x89 || opcode == 0x99) + if (opcode == LDA || opcode == 0x19 || opcode == 0x39 || opcode == 0x59 || opcode == 0x79 || opcode == 0x99 || opcode == 0xB9 || opcode == 0xD9) cpu->a[thread] = value; - if (opcode == LDY || opcode == 0x5A || opcode == 0x7A || opcode == 0x8A) + if (opcode == LDY || opcode == 0x1A || opcode == 0x3A || opcode == 0x5A || opcode == 0x7A || opcode == 0x9A) cpu->y[thread] = value; - if (opcode == LDX || opcode == 0x5C || opcode == 0x7C || opcode == 0x9C) + if (opcode == LDX || opcode == 0x1B || opcode == 0x3B || opcode == 0x5B || opcode == 0x7B || opcode == 0x9B) cpu->x[thread] = value; cpu->z[thread] = (value == 0); cpu->n[thread] = (value >> 63); @@ -1195,25 +983,6 @@ void *run(void *args) { break; case BEQ: /* BEQ Absolute. */ case 0xA4: /* BEQ Zero Matrix. */ - if (opcode == BEQ) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (cpu->z[thread]) cpu->pc[thread] = address; break; @@ -1221,33 +990,7 @@ void *run(void *args) { case RLB: /* Rotate Left accumulator by B. */ case 0x73: /* ROL Absolute. */ case 0x75: /* ROL Zero Matrix. */ - if (opcode != RLB) { - if (opcode == ROL) { - address = cpu->pc[thread]; - cpu->pc[thread]++; - } - if (opcode == 0x73) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x75) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - } else { + if (opcode == RLB) { value = cpu->b[thread]; } sum = cpu->a[thread] << value; @@ -1266,25 +1009,6 @@ void *run(void *args) { break; case BNE: /* BNE Absolute. */ case 0xB4: /* BNE Zero Matrix. */ - if (opcode == BNE) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (!cpu->z[thread]) cpu->pc[thread] = address; break; @@ -1292,33 +1016,7 @@ void *run(void *args) { case RRB: /* Rotate Right accumulator by B. */ case 0x83: /* ROR Absolute. */ case 0x85: /* ROR Zero Matrix. */ - if (opcode != RRB) { - if (opcode == ROR) { - address = cpu->pc[thread]; - cpu->pc[thread]++; - } - if (opcode == 0x83) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x85) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - } else { + if (opcode == RRB) { value = cpu->b[thread]; } sum = cpu->a[thread] >> value; @@ -1337,25 +1035,6 @@ void *run(void *args) { break; case BVS: /* BVS Absolute. */ case 0xC4: /* BVS Zero Matrix. */ - if (opcode == BVS) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (cpu->v[thread]) cpu->pc[thread] = address; break; @@ -1363,46 +1042,7 @@ void *run(void *args) { case MAB: /* Multiply Accumulator by B. */ case 0x93: /* MUL Absolute. */ case 0x95: /* MUL Zero Matrix. */ - if (opcode != MAB) { - if (opcode == MUL) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } - if (opcode == 0x93) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0x95) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - if (regsize >= 2) { - value += (uint64_t)addr[address+1] << 8; - } - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } - } else { + if (opcode == MAB) { value = cpu->b[thread]; } sum = cpu->a[thread]*value+cpu->c[thread]; @@ -1422,25 +1062,6 @@ void *run(void *args) { break; case BVC: /* BVC Absolute. */ case 0xD4: /* BVC Zero Matrix. */ - if (opcode == BVC) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } if (!cpu->v[thread]) cpu->pc[thread] = address; break; @@ -1449,44 +1070,6 @@ void *run(void *args) { case 0xA3: /* DIV Absolute. */ case 0xA5: /* DIV Zero Matrix. */ if (opcode != DAB) { - if (opcode == DIV) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } - if (opcode == 0xA3) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0xA5) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } - value = addr[address]; - if (regsize >= 2) { - value += (uint64_t)addr[address+1] << 8; - } - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } cpu->b[thread] = cpu->a[thread] % value; } else { value = cpu->b[thread]; @@ -1504,7 +1087,11 @@ void *run(void *args) { (cpu->ps &= ~(V << 8*thread)); break; case RTS: /* ReTurn from Subroutine. */ - for (uint8_t i = 0; i < 32; i+=8) { + if (addrsize) + stksize = 32; + else + stksize = 8; + for (uint8_t i = 0; i < stksize; i+=8) { cpu->sp[thread]++; if (i) cpu->pc[thread] += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i; @@ -1517,93 +1104,46 @@ void *run(void *args) { case CAB: /* Compare Accumulator, and B. */ case CPY: /* CPY Immediate. */ case CPX: /* CPX Immediate. */ - case 0x2B: /* CPY Absolute. */ - case 0x2D: /* CPX Absolute. */ + case 0xCA: /* CPY Absolute. */ + case 0xCB: /* CPX Absolute. */ case 0xB3: /* CMP Absolute. */ - case 0xE6: /* CPB Absolute. */ - case 0x3B: /* CPY Zero Matrix. */ - case 0x3D: /* CPX Zero Matrix. */ + case 0x36: /* CPB Absolute. */ + case 0xDA: /* CPY Zero Matrix. */ + case 0xDB: /* CPX Zero Matrix. */ case 0xB5: /* CMP Zero Matrix. */ - case 0xF6: /* CPB Zero Matrix. */ - case 0xE9: /* CMP Indirect. */ + case 0x46: /* CPB Zero Matrix. */ + case 0xF1: /* CMP Indirect. */ case 0xEA: /* CPY Indirect. */ - case 0xEC: /* CPX Indirect. */ - case 0xDF: /* CPB Indirect. */ - case 0xEB: /* CMP Indexed Indirect. */ + case 0xEB: /* CPX Indirect. */ + case 0x56: /* CPB Indirect. */ + case 0xF3: /* CMP Indexed Indirect. */ case 0xFA: /* CPY Indexed Indirect. */ - case 0xEF: /* CPB Indexed Indirect. */ - case 0xED: /* CMP Indirect Indexed. */ - case 0xFC: /* CPX Indirect Indexed. */ - case 0xFF: /* CPB Indirect Indexed. */ - if (opcode != CAB) { - if (opcode == CMP || opcode == CPY || opcode == CPX || opcode == CPB) { - address = cpu->pc[thread]; - cpu->pc[thread]+=regsize; - } else if (opcode == 0xB3 || opcode == 0x2B || opcode == 0x2D) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } else { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - if (opcode == 0xDF || opcode == 0xE9 || opcode == 0xEA || opcode == 0xEB || opcode == 0xEC || - opcode == 0xED || opcode == 0xEF || opcode == 0xFA || opcode == 0xFC || opcode == 0xFF) { - address = (uint64_t)addr[address] - | (uint64_t)addr[address+1] << 8 - | (uint64_t)addr[address+2] << 16 - | (uint64_t)addr[address+3] << 24 - | (uint64_t)addr[address+4] << 32 - | (uint64_t)addr[address+5] << 40 - | (uint64_t)addr[address+6] << 48 - | (uint64_t)addr[address+7] << 56; - if (opcode == 0xEB || opcode == 0xEF || opcode == 0xFA) - address += cpu->x[thread]; - if (opcode == 0xED || opcode == 0xFC || opcode == 0xFF) - address += cpu->y[thread]; - } - cpu->pc[thread]+=4; - iclk++; - } - value = (uint64_t)addr[address]; - if (regsize >= 2) - value += (uint64_t)addr[address+1] << 8; - if (regsize >= 4) { - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)addr[address+3] << 24; - } - if (regsize >= 8) { - value += (uint64_t)addr[address+4] << 32; - value += (uint64_t)addr[address+5] << 40; - value += (uint64_t)addr[address+6] << 48; - value += (uint64_t)addr[address+7] << 56; - } - } else { + case 0x66: /* CPB Indexed Indirect. */ + case 0xF5: /* CMP Indirect Indexed. */ + case 0xFB: /* CPX Indirect Indexed. */ + case 0x76: /* CPB Indirect Indexed. */ + if (opcode == CAB) { value = cpu->b[thread]; } - if (opcode == CMP || opcode == CAB || opcode == 0xE5 || opcode == 0xF5) - sum = cpu->a[thread]-value; - if (opcode == CPY || opcode == 0xE2 || opcode == 0xF2) - sum = cpu->y[thread]-value; - if (opcode == CPX || opcode == 0xE4 || opcode == 0xF4) - sum = cpu->x[thread]-value; + if (opcode == CPB || opcode == 0x36 || opcode == 0x46 || opcode == 0x56 || opcode == 0x66 || opcode == 0x76) + reg = cpu->b[thread]; + if (opcode == CMP || opcode == CAB || opcode == 0xB3 || opcode == 0xB5 || opcode == 0xF1 || opcode == 0xF3 || opcode == 0xF5) + reg = cpu->a[thread]; + if (opcode == CPY || opcode == 0xCA || opcode == 0xDA || opcode == 0xEA || opcode == 0xFA) + reg = cpu->y[thread]; + if (opcode == CPX || opcode == 0xCB || opcode == 0xDB || opcode == 0xEB || opcode == 0xFB) + reg = cpu->x[thread]; + sum = reg-value; cpu->n[thread] = (sum & 0x8000000000000000) ? 1 : 0; + cpu->v[thread] = ((reg^value) & 0x8000000000000000) && ((reg^sum) & 0x8000000000000000); cpu->z[thread] = (sum == 0) ? 1 : 0; cpu->c[thread] = (sum > value) ? 1 : 0; - (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->v[thread]) ? (cpu->ps |= (V << 8*thread)) : (cpu->ps &= ~(V << 8*thread)); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); break; case ENT: /* ENd Thread. */ - value = addr[address]; cpu->crt &= ~value; for (uint8_t i = 0; i < 7; i++) if ((value >> i) & 1) @@ -1648,27 +1188,6 @@ void *run(void *args) { case 0x14: /* JMP Indexed Indirect. */ case 0x24: /* JMP Indirect Indexed. */ case 0xD0: /* JMP Zero Matrix. */ - address = (uint32_t)addr[cpu->pc[thread]] - |(uint32_t)addr[cpu->pc[thread]+1] << 8 - |(uint32_t)addr[cpu->pc[thread]+2] << 16 - |(uint32_t)addr[cpu->pc[thread]+3] << 24; - - if (opcode == 0x04 || opcode == 0x14 || opcode == 0x24) { - address = (uint64_t)addr[address] - | (uint64_t)addr[address+1] << 8 - | (uint64_t)addr[address+2] << 16 - | (uint64_t)addr[address+3] << 24 - | (uint64_t)addr[address+4] << 32 - | (uint64_t)addr[address+5] << 40 - | (uint64_t)addr[address+6] << 48 - | (uint64_t)addr[address+7] << 56; - if (opcode == 0x14) - address += cpu->x[thread]; - if (opcode == 0x24) - address += cpu->y[thread]; - } - cpu->pc[thread]+=4; - iclk++; cpu->pc[thread] = address; break; @@ -1697,16 +1216,11 @@ void *run(void *args) { (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); break; case JSL: /* Jump to Subroutine Long. */ - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - for (int8_t i = 56; i >= 0; i-=8) { + if (addrsize) + stksize = 56; + else + stksize = 8; + for (int8_t i = stksize; i >= 0; i-=8) { if (i) addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> i; else @@ -1717,63 +1231,25 @@ void *run(void *args) { break; case 0xC3: /* INC Absolute. */ case 0xC5: /* INC Zero Matrix. */ - if (opcode == 0xC3) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0xC5) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } addr[address]++; break; case NOP: /* No OPeration. */ break; case RTL: /* ReTurn from subroutine Long. */ - for (uint8_t i = 0; i < 64; i+=8) { + if (addrsize) + stksize = 64; + else + stksize = 16; + for (uint8_t i = 0; i < stksize; i+=8) { cpu->sp[thread]++; - if (i < 56) - cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i; - else if (i == 56) - cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i + 1; + if (i) + cpu->pc[thread] += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i; else cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; } break; case 0xD3: /* DEC Absolute. */ case 0xD5: /* DEC Zero Matrix. */ - if (opcode == 0xD3) { - address = (uint64_t)addr[cpu->pc[thread]] - | (uint64_t)addr[cpu->pc[thread]+1] << 8 - | (uint64_t)addr[cpu->pc[thread]+2] << 16 - | (uint64_t)addr[cpu->pc[thread]+3] << 24 - | (uint64_t)addr[cpu->pc[thread]+4] << 32 - | (uint64_t)addr[cpu->pc[thread]+5] << 40 - | (uint64_t)addr[cpu->pc[thread]+6] << 48 - | (uint64_t)addr[cpu->pc[thread]+7] << 56; - cpu->pc[thread]+=8; - iclk++; - } - if (opcode == 0xD5) { - address = addr[cpu->pc[thread]] - | addr[cpu->pc[thread]+1] << 8 - | addr[cpu->pc[thread]+2] << 16 - | addr[cpu->pc[thread]+3] << 24; - cpu->pc[thread]+=4; - iclk++; - } addr[address]--; break; case BRK: /* BReaK. */ @@ -1810,18 +1286,17 @@ void *run(void *args) { break; } ins++; - usleep(100000); #if debug && !bench #if keypoll pthread_mutex_lock(&mutex); #endif - mvwprintw(scr, getmaxy(scr)-lines, 0, "Operand: $%llx" + /*mvwprintw(scr, getmaxy(scr)-lines, 0, "Operand: $%llx" ", $%04llx: $%02x, $%04llx: $%02x" ", $1000: $%02x, $1001: $%02x " , value , RX_ADDR, addr[RX_ADDR], TX_ADDR, addr[TX_ADDR] - , addr[0x1000], addr[0x1001]); - mvwprintw(scr, (24*thread)+1, 0, "Instructions executed: %llu, Clock cycles: %llu\r", ins, iclk); + , addr[0x1000], addr[0x1001]);*/ + mvwprintw(scr, (6*thread)+1, 0, "Instructions executed: %llu, Clock cycles: %llu\r", ins, iclk); wrefresh(scr); #if keypoll pthread_mutex_unlock(&mutex); @@ -1830,12 +1305,12 @@ void *run(void *args) { #if bench if (ins >= BENCH_INST) { end = 1; - pthread_mutex_lock(&mutex); + pthread_mutex_lock(&main_mutex); threads_done++; inst[thread] = ins; clk[thread] = iclk; pthread_cond_signal(&main_cond); - pthread_mutex_unlock(&mutex); + pthread_mutex_unlock(&main_mutex); gettimeofday(&en[thread], 0); } #endif @@ -1861,6 +1336,7 @@ int main(int argc, char **argv) { sprintf(tmp, "\033[2J\033[H"); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); +#if !bench if(!scr) scr = initscr(); nodelay(stdscr, 0); @@ -1876,11 +1352,13 @@ int main(int argc, char **argv) { init_pair(1, COLOR_WHITE, -1); attron(COLOR_PAIR(1) | A_BOLD); wmove(scr, 0, 0); +#endif for (int i = 0; i < THREADS; i++) { thr[i].sx.sp[i] = 0xFFFF; thr[i].sx.stk_st[i] = i+1; if (i) { thr[i].sx.a[i] = 0; + thr[i].sx.b[i] = 0; thr[i].sx.x[i] = 0; thr[i].sx.y[i] = 0; thr[i].sx.pc[i] = (uint64_t)addr[0xFF50+(8*(i-1))] @@ -1893,6 +1371,7 @@ int main(int argc, char **argv) { | (uint64_t)addr[0xFF57+(8*(i-1))] << 56; } else { thr[i].sx.a[i] = 0; + thr[i].sx.b[i] = 0; thr[i].sx.x[i] = 0; thr[i].sx.y[i] = 0; thr[i].sx.pc[i] = (uint64_t)addr[0xFFC0] @@ -1916,10 +1395,12 @@ int main(int argc, char **argv) { assert(!result); } int c = 0; +#if !bench werase(scr); +#endif while (threads_done < THREADS) { - int x, y, i = 0; #if !bench + int x, y, i = 0; if ((c != EOF && c !=-1)) { pthread_mutex_lock(&main_mutex); curs_set(0); @@ -1945,6 +1426,7 @@ int main(int argc, char **argv) { default: addr[RX_ADDR] = (uint8_t)c; addr[CTRL_ADDR] = 1; + kbd_rdy = 1; #if !keypoll pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); @@ -1963,10 +1445,6 @@ int main(int argc, char **argv) { } #if bench if (threads_done == THREADS) { - #if en_nc - scr = NULL; - endwin(); - #endif double tm_sec, tm_usec, tm[THREADS], ttm; double clkspd; double mhz; @@ -7,15 +7,17 @@ reset: start: lda.q #$-FFFF + ldb.q #-1 signshft: - asr #$1 - cmp.q #$-1 + asr #1 + cab beq start jmp signshft .org $FFC0 .qword reset .org $0 +v done diff --git a/test/fib2.s b/test/fib2.s new file mode 100644 index 0000000..d8c0d42 --- /dev/null +++ b/test/fib2.s @@ -0,0 +1,26 @@ +; Variables for thread 0. +.org $1000 +x: + .qword $0 +y: + .qword $1 +z: + .qword $0 + +.org $0 +init: + cps ; Clear the Processor Status register. + +start: + lda #0 ; Clear the accumulator. + ldb.q y ; b=1. +fib: + aab ; Add x with y. + ldb.q y + stb.q x ; x=y. + sta.q y ; y=z. + tab + lda.q x + bcs start ; Start all over again, if the carry flag was set. + jmp fib ; Otherwise, keep looping. +done diff --git a/test/ind-addr.s b/test/ind-addr.s new file mode 100644 index 0000000..0c9365b --- /dev/null +++ b/test/ind-addr.s @@ -0,0 +1,27 @@ +.org $0 +reset: + cps + lda #1 + ldb #1 +main: + jsr (rot) + jmp main + +rotate_left: + rlb + rts + +rotate_right: + rrb + rts + +.org $1000 +rot: + .qword rotate_left +r +.org $0 +v +.org $1000 +v +done + diff --git a/test/input.s b/test/input.s index 20ab3d1..a8b0830 100644 --- a/test/input.s +++ b/test/input.s @@ -4,22 +4,26 @@ ; mr b0nk 500 <b0nk@b0nk.xyz> +; Input buffer. +.org $4000 +buffer: + ; Initalize some variables. -.org $1000 +.org $0 scr_row: .byte $0 scr_col: .byte $0 a: - .word $0 + .byte $0 b: - .word $0 + .byte $0 c: - .word $0 + .byte $0 d: - .word $0 + .byte $0 e: - .word $0 + .byte $0 string: .byte "Please, type something.\n" string2: @@ -27,9 +31,9 @@ string2: end: .byte $0 -; Input buffer. -.org $0000 -buffer: +; String Pointer +ptr: + .qword buffer ; Main program .org $8000 @@ -37,35 +41,32 @@ reset: cps ldx.w #$FFFF txs - ldy #$0 + ldy #0 + lda #0 clr_buf: - lda #$0 - cpy.w #$1000 + cpy.w #$FFF beq start - sta buffer, y + sta (ptr), y iny jmp clr_buf start: - ldx.w #$0 ; Reset x. - ldy.w #$0 ; Reset y. + tax ; Reset x. + tay ; Reset y. jmp print rset_a: - lda #$10 -delay: - beq read - dec - jmp delay -sleep: - lda end - bne spin ; Are we done with getting input? + lda #1 + read: lda $C000 ; Get control register. beq rset_a ; Loop until we get a character. - lda #$0 + lda #0 sta $C000 jmp getchar ; We got a key. +sleep: + lda end + bne spin ; Are we done with getting input? print: lda string, x ; Get character at offset x. @@ -78,7 +79,7 @@ print: jmp print inc_row: inc scr_row - lda #$0 + lda #0 sta scr_col jmp print ; Keep printing more characters. @@ -88,26 +89,26 @@ getchar: beq esc cmp #$A beq nl ; Did the user type a newline? - cmp #$8 + cmp #8 beq bs ; Did the user type a backspace? cmp #$7F beq bs ; Did the user type a backspace? echo: sta a ldx scr_col - cpx #$4F + cpx #79 bne echo_print linewrap: inc scr_row - ldx #$0 + ldx #0 stx scr_col lda scr_row - jsr update_pos + jsl update_pos echo_print: lda a sta $C001 ; Echo typed character. inc scr_col ; Increment the cursor's x coordinate. - sta buffer, y ; Store typed character into the input buffer. + sta (ptr), y ; Store typed character into the input buffer. iny jmp rset_a ; Start getting user input. @@ -117,22 +118,22 @@ esc: beq read ; We have an error, so discard it, and go back to getting user input. lda $C002 ; Get the escape code. sta c ; Store the escape code, until we need it. - jsr isup ; Check if the user pressed up. + jsl isup ; Check if the user pressed up. lda d - cmp #$0 + cmp #0 bne esc_end - jsr isdown ; Check if the user pressed down. + jsl isdown ; Check if the user pressed down. lda d - cmp #$0 + cmp #0 bne esc_end - lda #$0 - jsr isleft ; Check if the user pressed left. + lda #0 + jsl isleft ; Check if the user pressed left. lda d - cmp #$0 + cmp #0 bne esc_end - jsr isright ; Check if the user pressed right. + jsl isright ; Check if the user pressed right. esc_end: - lda #$0 + lda #0 sta d jmp rset_a ; Go back to getting user input. @@ -143,27 +144,27 @@ isup: cmp #$41 ; Did the user press the up arrow key? beq up ; Yes, so move the cursor up. isup_done: - rts ; End of isup. + rtl ; End of isup. isdown: lda scr_row ; Start checking the y coordinate of the cursor. - cmp #$17 ; Is the cursor at the bottom of the screen? + cmp #23 ; Is the cursor at the bottom of the screen? beq isdown_done ; Yes, so return. lda c ; No, so load the escape code back into the accumulator. cmp #$42 ; Did the user press the down arrow key? beq down ; Yes, so move the cursor down. isdown_done: - rts ; End of isdown. + rtl ; End of isdown. isright: lda scr_col ; Start checking the x coordinate of the cursor. - cmp #$4F ; Is the cursor at the far right of the screen? + cmp #79 ; Is the cursor at the far right of the screen? beq isright_end ; Yes, so return. lda c ; No, so load the escape code back into the accumulator. cmp #$43 ; Did the user press the right arrow key? beq right ; Yes, so move the cursor right. isright_end: - rts ; End of isright. + rtl ; End of isright. isleft: lda scr_col ; Is the cursor at the far left of the screen? @@ -172,36 +173,28 @@ isleft: cmp #$44 ; Did the user press the left arrow key? beq left ; Yes, so move the cursor left. isleft_done: - rts ; End of isleft. + rtl ; End of isleft. up: dec scr_row - lda #$0 - sta e - jsr update_pos - lda #$1 + jsl update_pos + lda #1 sta d jmp isup_done down: inc scr_row - lda #$1 - sta e - jsr update_pos - lda #$1 + jsl update_pos + lda #1 sta d jmp isdown_done right: inc scr_col - lda #$2 - sta e - jsr update_pos + jsl update_pos jmp isright_end left: dec scr_col - lda #$3 - sta e - jsr update_pos - lda #$1 + jsl update_pos + lda #1 sta d jmp isleft_done @@ -210,74 +203,65 @@ update_pos: sta $C001 ; to the screen. lda #$5B ; Print '[' sta $C001 ; to the screen, and start the escape sequence. - jsr getrow ; Start printing the row number to the screen. - jsr getcol ; Start printing the column number to the screen. + jsl getrow ; Start printing the row number to the screen. + jsl getcol ; Start printing the column number to the screen. lda #$48 ; Print 'H' sta $C001 ; to the screen. - rts ; End of update_pos. + rtl ; End of update_pos. getrow: lda scr_row ; Get the cursor's y coordinate. - div #$A ; Divide A by 10. + div #10 ; Divide A by 10. adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. tba ; Get the remainder. adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. - rts ; End of getrow. + rtl ; End of getrow. getcol: lda #$3B ; Print ';' sta $C001 ; to the screen. lda scr_col ; Get the cursor's x coordinate. - div #$A ; Divide A by 10. + div #10 ; Divide A by 10. adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. tba ; Get the remainder. adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. - rts ; End of getrow. + rtl ; End of getrow. -uint_to_bcd: - div #$A ; Divide A by 10. - lsl #$4 ; Shift the result left by 4 bits. - sta a ; Store the result for later. - tba ; Get the remainder. - sta b ; Store the remainder for later. - lda a ; Get the result. - ora b ; Or the result, with the remainder. - rts ; We've converted the value to BCD, so return. nl: lda #$A sta $C001 inc scr_row - lda #$0 ; Replace newline with a null terminator. - sta buffer, y ; Store said terminator into the input buffer. + lda #0 ; Replace newline with a null terminator. + sta (ptr), y ; Store said terminator into the input buffer. sta scr_col - ldy.w #$0 ; Reset y, to print the result. + ldy.w #0 ; Reset y, to print the result. jmp result back: sta $C001 ; Print backspace. - lda #$0 ; Put a null terminator, in place of the backspace. - sta buffer, y ; Place it into the input buffer. + lda #0 ; Put a null terminator, in place of the backspace. + sta (ptr), y ; Place it into the input buffer. dey ; Decrement buffer offset. dec scr_col jmp read ; Get next character. bs: - cpy #$0 ; Are we at the start of the buffer? + cpy #0 ; Are we at the start of the buffer? beq rset_a ; We are, so do not store the backspace into the buffer. jmp back ; We are not, so add the backspace to the buffer. result: ldx scr_col - cpx #$4F + cpx #79 bne result_print linewrap2: inc scr_row ldx #$0 stx scr_col - jsr update_pos + jsl update_pos result_print: lda string2, y beq rset_y ; Reset y, if we hit the null terminator. @@ -288,20 +272,20 @@ result_print: rset_y: - ldy.w #$0 ; Reset y. + ldy.w #0 ; Reset y. jmp print_buf ; Print the input buffer. print_buf: ldx scr_col - cpx #$4F + cpx #79 bne buf_print linewrap3: inc scr_row - ldx #$0 + ldx #0 stx scr_col - jsr update_pos + jsl update_pos buf_print: - lda buffer, y ; Get a character from the input buffer. + lda (ptr), y ; Get a character from the input buffer. beq spin ; Are we done with printing the buffer? sta $C001 ; Print said character. inc scr_col ; Increment the cursor's x coordinate. @@ -310,11 +294,11 @@ buf_print: scr_to_buf: tax - mul #$50 + mul #80 adc scr_col tay txa - rts + rtl spin: nop @@ -322,6 +306,20 @@ spin: nop jmp spin +.org $1000 +v +.org $1100 +v +.org $1200 +v +.org $8000 +v +.org $8100 +v +.org $8200 +v +.org $8300 +v .org $FFC0 .qword reset @@ -333,15 +331,8 @@ spin: .qword spin .qword spin .qword spin - -.org $FFA0 -.qword irq_routine -;.org $8000 -;viewmem -;.org $8100 -;viewmem -;.org $8200 -;viewmem -;q -done +.org $FF50 +v +;done +q diff --git a/test/test-stack.s b/test/test-stack.s index 5c7e0fd..193cca7 100644 --- a/test/test-stack.s +++ b/test/test-stack.s @@ -2,10 +2,9 @@ init: cps ldx.w #$FFFF txs -ldx.d #$00 loop: -iax +iab pha #$08 ply #$08 jmp loop diff --git a/test/the-tests.s b/test/the-tests.s new file mode 100644 index 0000000..ae31e26 --- /dev/null +++ b/test/the-tests.s @@ -0,0 +1,35 @@ +.org $0 +init: + cps + +lstart: + lda #1 + tab + +lshft: + llb + bcs rstart + jmp lshft + +rstart: + tba + lsl #63 + +rshft: + lrb + bcs lstart + jmp rshft + +.org $FFC0 +.qword init + +.org $FF50 +.qword init +.qword init +.qword init +.qword init +.qword init +.qword init +.qword init +.qword init +done |