├── 6809.c ├── 6809.h ├── COPYING ├── Makefile.am ├── Makefile.in ├── README ├── command.c ├── config.h.in ├── configure ├── configure.ac ├── disk.c ├── eon.c ├── eon.h ├── fileio.c ├── imux.c ├── ioexpand.c ├── machine.c ├── machine.h ├── main.c ├── mmu.c ├── monitor.c ├── monitor.h ├── prog ├── hello.c ├── infloop.c └── string.c ├── serial.c ├── symtab.c ├── timer.c ├── wpc-run ├── wpc.c ├── wpclib.c └── wpclib.h /6809.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2001 by Arto Salmi and Joze Fabcic 3 | * Copyright 2006 by Brian Dominy 4 | * 5 | * This file is part of GCC6809. 6 | * 7 | * GCC6809 is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * GCC6809 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GCC6809; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | 23 | #ifndef M6809_H 24 | #define M6809_H 25 | 26 | #include "config.h" 27 | #include 28 | #ifdef HAVE_STDLIB_H 29 | # include 30 | #else 31 | #error 32 | #endif 33 | #ifdef HAVE_STRING_H 34 | # include 35 | #else 36 | #error 37 | #endif 38 | #ifdef HAVE_STDINT_H 39 | # include 40 | #else 41 | #error 42 | #endif 43 | 44 | typedef uint8_t UINT8; 45 | typedef signed char INT8; 46 | 47 | typedef uint16_t UINT16; 48 | typedef signed short INT16; 49 | 50 | typedef uint32_t UINT32; 51 | typedef signed int INT32; 52 | 53 | typedef uint16_t target_addr_t; 54 | 55 | #include "machine.h" 56 | 57 | #define E_FLAG 0x80 58 | #define F_FLAG 0x40 59 | #define H_FLAG 0x20 60 | #define I_FLAG 0x10 61 | #define N_FLAG 0x08 62 | #define Z_FLAG 0x04 63 | #define V_FLAG 0x02 64 | #define C_FLAG 0x01 65 | 66 | extern int debug_enabled; 67 | extern int need_flush; 68 | extern unsigned long total; 69 | extern int dump_cycles_on_success; 70 | extern const char *prog_name; 71 | 72 | long get_elapsed_realtime (void); 73 | 74 | /* Primitive read/write macros */ 75 | #define read8(addr) cpu_read8 (addr) 76 | #define write8(addr,val) do { cpu_write8 (addr, val); } while (0) 77 | 78 | /* 16-bit versions */ 79 | #define read16(addr) cpu_read16(addr) 80 | #define write16(addr,val) do { write8(addr+1, val & 0xFF); write8(addr, (val >> 8) & 0xFF); } while (0) 81 | 82 | /* Fetch macros */ 83 | 84 | #define abs_read16(addr) ((abs_read8(addr) << 8) | abs_read8(addr+1)) 85 | 86 | #define fetch8() abs_read8 (pc++) 87 | #define fetch16() (pc += 2, abs_read16(pc-2)) 88 | 89 | /* 6809.c */ 90 | extern int cpu_quit; 91 | extern int cpu_execute (int); 92 | extern void cpu_reset (void); 93 | 94 | extern unsigned get_a (void); 95 | extern unsigned get_b (void); 96 | extern unsigned get_cc (void); 97 | extern unsigned get_dp (void); 98 | extern unsigned get_x (void); 99 | extern unsigned get_y (void); 100 | extern unsigned get_s (void); 101 | extern unsigned get_u (void); 102 | extern unsigned get_pc (void); 103 | extern unsigned get_d (void); 104 | extern unsigned get_flags (void); 105 | extern void set_a (unsigned); 106 | extern void set_b (unsigned); 107 | extern void set_cc (unsigned); 108 | extern void set_dp (unsigned); 109 | extern void set_x (unsigned); 110 | extern void set_y (unsigned); 111 | extern void set_s (unsigned); 112 | extern void set_u (unsigned); 113 | extern void set_pc (unsigned); 114 | extern void set_d (unsigned); 115 | 116 | /* fileio.c */ 117 | 118 | struct pathlist 119 | { 120 | int count; 121 | char *entry[32]; 122 | }; 123 | 124 | 125 | void path_init (struct pathlist *path); 126 | void path_add (struct pathlist *path, const char *dir); 127 | FILE * file_open (struct pathlist *path, const char *filename, const char *mode); 128 | FILE * file_require_open (struct pathlist *path, const char *filename, const char *mode); 129 | void file_close (FILE *fp); 130 | 131 | /* monitor.c */ 132 | extern int monitor_on; 133 | extern int check_break (void); 134 | extern void monitor_init (void); 135 | extern int monitor6809 (void); 136 | extern int dasm (char *, absolute_address_t); 137 | 138 | extern int load_hex (const char *); 139 | extern int load_s19 (const char *); 140 | extern int load_bin (const char *,int); 141 | 142 | #define MAX_STRINGSPACE 32000 143 | #define MAX_SYMBOL_HASH 1009 144 | 145 | #define SYM_DEFAULT 0 146 | #define SYM_AUTO 1 147 | 148 | 149 | typedef struct 150 | { 151 | unsigned char format; 152 | unsigned int size; 153 | } datatype_t; 154 | 155 | 156 | /* symtab.c */ 157 | struct stringspace 158 | { 159 | char space[32000]; 160 | unsigned int used; 161 | }; 162 | 163 | 164 | struct symbol 165 | { 166 | char *name; 167 | unsigned long value; 168 | datatype_t ty; 169 | unsigned int type; 170 | struct symbol *name_chain; 171 | struct symbol *value_chain; 172 | }; 173 | 174 | 175 | struct symtab 176 | { 177 | struct symbol *syms_by_name[MAX_SYMBOL_HASH]; 178 | struct symbol *syms_by_value[MAX_SYMBOL_HASH]; 179 | struct symtab *parent; 180 | }; 181 | 182 | extern struct symtab program_symtab; 183 | extern struct symtab internal_symtab; 184 | extern struct symtab auto_symtab; 185 | 186 | struct symbol *sym_add (struct symtab *symtab, const char *name, unsigned long value, unsigned int type); 187 | void sym_set (struct symtab *symtab, const char *name, unsigned long value, unsigned int type); 188 | int sym_find (struct symtab *symtab, const char *name, unsigned long *value, unsigned int type); 189 | const char *sym_lookup (struct symtab *symtab, unsigned long value); 190 | 191 | typedef void (*command_handler_t) (void); 192 | 193 | typedef void (*virtual_handler_t) (unsigned long *val, int writep); 194 | 195 | typedef unsigned int thread_id_t; 196 | 197 | typedef struct 198 | { 199 | unsigned int id : 8; 200 | unsigned int used : 1; 201 | unsigned int enabled : 1; 202 | unsigned int conditional : 1; 203 | unsigned int threaded : 1; 204 | unsigned int on_read : 1; 205 | unsigned int on_write : 1; 206 | unsigned int on_execute : 1; 207 | unsigned int size : 4; 208 | unsigned int keep_running : 1; 209 | unsigned int temp : 1; 210 | unsigned int last_write : 16; 211 | unsigned int write_mask : 16; 212 | absolute_address_t addr; 213 | char condition[128]; 214 | thread_id_t tid; 215 | unsigned int pass_count; 216 | unsigned int ignore_count; 217 | } breakpoint_t; 218 | 219 | 220 | 221 | typedef struct 222 | { 223 | int used : 1; 224 | datatype_t type; 225 | char expr[128]; 226 | } display_t; 227 | 228 | 229 | typedef struct 230 | { 231 | int id : 8; 232 | thread_id_t tid; 233 | } thread_t; 234 | 235 | 236 | #define MAX_BREAKS 32 237 | #define MAX_DISPLAYS 32 238 | #define MAX_HISTORY 10 239 | #define MAX_THREADS 64 240 | 241 | void command_irq_hook (unsigned long cycles); 242 | 243 | #endif /* M6809_H */ 244 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | m6809_run_SOURCES = \ 2 | 6809.c main.c monitor.c machine.c eon.c wpc.c \ 3 | symtab.c command.c fileio.c wpclib.c imux.c \ 4 | ioexpand.c mmu.c timer.c serial.c disk.c \ 5 | 6809.h config.h eon.h machine.h monitor.h wpclib.h 6 | 7 | LIBS = $(READLINE_LIBS) 8 | 9 | bin_PROGRAMS = m6809-run 10 | bin_SCRIPTS = wpc-run 11 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.9.6 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005 Free Software Foundation, Inc. 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | 17 | 18 | srcdir = @srcdir@ 19 | top_srcdir = @top_srcdir@ 20 | VPATH = @srcdir@ 21 | pkgdatadir = $(datadir)/@PACKAGE@ 22 | pkglibdir = $(libdir)/@PACKAGE@ 23 | pkgincludedir = $(includedir)/@PACKAGE@ 24 | top_builddir = . 25 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 26 | INSTALL = @INSTALL@ 27 | install_sh_DATA = $(install_sh) -c -m 644 28 | install_sh_PROGRAM = $(install_sh) -c 29 | install_sh_SCRIPT = $(install_sh) -c 30 | INSTALL_HEADER = $(INSTALL_DATA) 31 | transform = $(program_transform_name) 32 | NORMAL_INSTALL = : 33 | PRE_INSTALL = : 34 | POST_INSTALL = : 35 | NORMAL_UNINSTALL = : 36 | PRE_UNINSTALL = : 37 | POST_UNINSTALL = : 38 | LIBOBJDIR = 39 | bin_PROGRAMS = m6809-run$(EXEEXT) 40 | subdir = . 41 | DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ 42 | $(srcdir)/Makefile.in $(srcdir)/config.h.in \ 43 | $(top_srcdir)/configure COPYING depcomp install-sh missing 44 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 45 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 46 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 47 | $(ACLOCAL_M4) 48 | am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ 49 | configure.lineno configure.status.lineno 50 | mkinstalldirs = $(install_sh) -d 51 | CONFIG_HEADER = config.h 52 | CONFIG_CLEAN_FILES = 53 | am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" 54 | binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) 55 | PROGRAMS = $(bin_PROGRAMS) 56 | am_m6809_run_OBJECTS = 6809.$(OBJEXT) main.$(OBJEXT) monitor.$(OBJEXT) \ 57 | machine.$(OBJEXT) eon.$(OBJEXT) wpc.$(OBJEXT) symtab.$(OBJEXT) \ 58 | command.$(OBJEXT) fileio.$(OBJEXT) wpclib.$(OBJEXT) \ 59 | imux.$(OBJEXT) ioexpand.$(OBJEXT) mmu.$(OBJEXT) \ 60 | timer.$(OBJEXT) serial.$(OBJEXT) disk.$(OBJEXT) 61 | m6809_run_OBJECTS = $(am_m6809_run_OBJECTS) 62 | m6809_run_LDADD = $(LDADD) 63 | binSCRIPT_INSTALL = $(INSTALL_SCRIPT) 64 | SCRIPTS = $(bin_SCRIPTS) 65 | DEFAULT_INCLUDES = -I. -I$(srcdir) -I. 66 | depcomp = $(SHELL) $(top_srcdir)/depcomp 67 | am__depfiles_maybe = depfiles 68 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ 69 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 70 | CCLD = $(CC) 71 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ 72 | SOURCES = $(m6809_run_SOURCES) 73 | DIST_SOURCES = $(m6809_run_SOURCES) 74 | ETAGS = etags 75 | CTAGS = ctags 76 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 77 | distdir = $(PACKAGE)-$(VERSION) 78 | top_distdir = $(distdir) 79 | am__remove_distdir = \ 80 | { test ! -d $(distdir) \ 81 | || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ 82 | && rm -fr $(distdir); }; } 83 | DIST_ARCHIVES = $(distdir).tar.gz 84 | GZIP_ENV = --best 85 | distuninstallcheck_listfiles = find . -type f -print 86 | distcleancheck_listfiles = find . -type f -print 87 | ACLOCAL = @ACLOCAL@ 88 | AMDEP_FALSE = @AMDEP_FALSE@ 89 | AMDEP_TRUE = @AMDEP_TRUE@ 90 | AMTAR = @AMTAR@ 91 | AUTOCONF = @AUTOCONF@ 92 | AUTOHEADER = @AUTOHEADER@ 93 | AUTOMAKE = @AUTOMAKE@ 94 | AWK = @AWK@ 95 | CC = @CC@ 96 | CCDEPMODE = @CCDEPMODE@ 97 | CFLAGS = @CFLAGS@ 98 | CPP = @CPP@ 99 | CPPFLAGS = @CPPFLAGS@ 100 | CYGPATH_W = @CYGPATH_W@ 101 | DEFS = @DEFS@ 102 | DEPDIR = @DEPDIR@ 103 | ECHO_C = @ECHO_C@ 104 | ECHO_N = @ECHO_N@ 105 | ECHO_T = @ECHO_T@ 106 | EGREP = @EGREP@ 107 | EXEEXT = @EXEEXT@ 108 | GREP = @GREP@ 109 | INSTALL_DATA = @INSTALL_DATA@ 110 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 111 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 112 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 113 | LDFLAGS = @LDFLAGS@ 114 | LIBOBJS = @LIBOBJS@ 115 | LIBS = $(READLINE_LIBS) 116 | LTLIBOBJS = @LTLIBOBJS@ 117 | MAKEINFO = @MAKEINFO@ 118 | OBJEXT = @OBJEXT@ 119 | PACKAGE = @PACKAGE@ 120 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 121 | PACKAGE_NAME = @PACKAGE_NAME@ 122 | PACKAGE_STRING = @PACKAGE_STRING@ 123 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 124 | PACKAGE_VERSION = @PACKAGE_VERSION@ 125 | PATH_SEPARATOR = @PATH_SEPARATOR@ 126 | READLINE_LIBS = @READLINE_LIBS@ 127 | SET_MAKE = @SET_MAKE@ 128 | SHELL = @SHELL@ 129 | STRIP = @STRIP@ 130 | VERSION = @VERSION@ 131 | ac_ct_CC = @ac_ct_CC@ 132 | am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ 133 | am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ 134 | am__include = @am__include@ 135 | am__leading_dot = @am__leading_dot@ 136 | am__quote = @am__quote@ 137 | am__tar = @am__tar@ 138 | am__untar = @am__untar@ 139 | bindir = @bindir@ 140 | build_alias = @build_alias@ 141 | datadir = @datadir@ 142 | datarootdir = @datarootdir@ 143 | docdir = @docdir@ 144 | dvidir = @dvidir@ 145 | exec_prefix = @exec_prefix@ 146 | host_alias = @host_alias@ 147 | htmldir = @htmldir@ 148 | includedir = @includedir@ 149 | infodir = @infodir@ 150 | install_sh = @install_sh@ 151 | libdir = @libdir@ 152 | libexecdir = @libexecdir@ 153 | localedir = @localedir@ 154 | localstatedir = @localstatedir@ 155 | mandir = @mandir@ 156 | mkdir_p = @mkdir_p@ 157 | oldincludedir = @oldincludedir@ 158 | pdfdir = @pdfdir@ 159 | prefix = @prefix@ 160 | program_transform_name = @program_transform_name@ 161 | psdir = @psdir@ 162 | sbindir = @sbindir@ 163 | sharedstatedir = @sharedstatedir@ 164 | sysconfdir = @sysconfdir@ 165 | target_alias = @target_alias@ 166 | m6809_run_SOURCES = \ 167 | 6809.c main.c monitor.c machine.c eon.c wpc.c \ 168 | symtab.c command.c fileio.c wpclib.c imux.c \ 169 | ioexpand.c mmu.c timer.c serial.c disk.c \ 170 | 6809.h config.h eon.h machine.h monitor.h wpclib.h 171 | 172 | bin_SCRIPTS = wpc-run 173 | all: config.h 174 | $(MAKE) $(AM_MAKEFLAGS) all-am 175 | 176 | .SUFFIXES: 177 | .SUFFIXES: .c .o .obj 178 | am--refresh: 179 | @: 180 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 181 | @for dep in $?; do \ 182 | case '$(am__configure_deps)' in \ 183 | *$$dep*) \ 184 | echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ 185 | cd $(srcdir) && $(AUTOMAKE) --foreign \ 186 | && exit 0; \ 187 | exit 1;; \ 188 | esac; \ 189 | done; \ 190 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ 191 | cd $(top_srcdir) && \ 192 | $(AUTOMAKE) --foreign Makefile 193 | .PRECIOUS: Makefile 194 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 195 | @case '$?' in \ 196 | *config.status*) \ 197 | echo ' $(SHELL) ./config.status'; \ 198 | $(SHELL) ./config.status;; \ 199 | *) \ 200 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ 201 | cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ 202 | esac; 203 | 204 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 205 | $(SHELL) ./config.status --recheck 206 | 207 | $(top_srcdir)/configure: $(am__configure_deps) 208 | cd $(srcdir) && $(AUTOCONF) 209 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 210 | cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) 211 | 212 | config.h: stamp-h1 213 | @if test ! -f $@; then \ 214 | rm -f stamp-h1; \ 215 | $(MAKE) stamp-h1; \ 216 | else :; fi 217 | 218 | stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status 219 | @rm -f stamp-h1 220 | cd $(top_builddir) && $(SHELL) ./config.status config.h 221 | $(srcdir)/config.h.in: $(am__configure_deps) 222 | cd $(top_srcdir) && $(AUTOHEADER) 223 | rm -f stamp-h1 224 | touch $@ 225 | 226 | distclean-hdr: 227 | -rm -f config.h stamp-h1 228 | install-binPROGRAMS: $(bin_PROGRAMS) 229 | @$(NORMAL_INSTALL) 230 | test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" 231 | @list='$(bin_PROGRAMS)'; for p in $$list; do \ 232 | p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ 233 | if test -f $$p \ 234 | ; then \ 235 | f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ 236 | echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ 237 | $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ 238 | else :; fi; \ 239 | done 240 | 241 | uninstall-binPROGRAMS: 242 | @$(NORMAL_UNINSTALL) 243 | @list='$(bin_PROGRAMS)'; for p in $$list; do \ 244 | f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ 245 | echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ 246 | rm -f "$(DESTDIR)$(bindir)/$$f"; \ 247 | done 248 | 249 | clean-binPROGRAMS: 250 | -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) 251 | m6809-run$(EXEEXT): $(m6809_run_OBJECTS) $(m6809_run_DEPENDENCIES) 252 | @rm -f m6809-run$(EXEEXT) 253 | $(LINK) $(m6809_run_LDFLAGS) $(m6809_run_OBJECTS) $(m6809_run_LDADD) $(LIBS) 254 | install-binSCRIPTS: $(bin_SCRIPTS) 255 | @$(NORMAL_INSTALL) 256 | test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" 257 | @list='$(bin_SCRIPTS)'; for p in $$list; do \ 258 | if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ 259 | if test -f $$d$$p; then \ 260 | f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ 261 | echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \ 262 | $(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \ 263 | else :; fi; \ 264 | done 265 | 266 | uninstall-binSCRIPTS: 267 | @$(NORMAL_UNINSTALL) 268 | @list='$(bin_SCRIPTS)'; for p in $$list; do \ 269 | f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ 270 | echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ 271 | rm -f "$(DESTDIR)$(bindir)/$$f"; \ 272 | done 273 | 274 | mostlyclean-compile: 275 | -rm -f *.$(OBJEXT) 276 | 277 | distclean-compile: 278 | -rm -f *.tab.c 279 | 280 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/6809.Po@am__quote@ 281 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command.Po@am__quote@ 282 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disk.Po@am__quote@ 283 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eon.Po@am__quote@ 284 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileio.Po@am__quote@ 285 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imux.Po@am__quote@ 286 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioexpand.Po@am__quote@ 287 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/machine.Po@am__quote@ 288 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ 289 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmu.Po@am__quote@ 290 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/monitor.Po@am__quote@ 291 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serial.Po@am__quote@ 292 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symtab.Po@am__quote@ 293 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@ 294 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wpc.Po@am__quote@ 295 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wpclib.Po@am__quote@ 296 | 297 | .c.o: 298 | @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ 299 | @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi 300 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 301 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 302 | @am__fastdepCC_FALSE@ $(COMPILE) -c $< 303 | 304 | .c.obj: 305 | @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ 306 | @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi 307 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 308 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 309 | @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` 310 | uninstall-info-am: 311 | 312 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) 313 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 314 | unique=`for i in $$list; do \ 315 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 316 | done | \ 317 | $(AWK) ' { files[$$0] = 1; } \ 318 | END { for (i in files) print i; }'`; \ 319 | mkid -fID $$unique 320 | tags: TAGS 321 | 322 | TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ 323 | $(TAGS_FILES) $(LISP) 324 | tags=; \ 325 | here=`pwd`; \ 326 | list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ 327 | unique=`for i in $$list; do \ 328 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 329 | done | \ 330 | $(AWK) ' { files[$$0] = 1; } \ 331 | END { for (i in files) print i; }'`; \ 332 | if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ 333 | test -n "$$unique" || unique=$$empty_fix; \ 334 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 335 | $$tags $$unique; \ 336 | fi 337 | ctags: CTAGS 338 | CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ 339 | $(TAGS_FILES) $(LISP) 340 | tags=; \ 341 | here=`pwd`; \ 342 | list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ 343 | unique=`for i in $$list; do \ 344 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 345 | done | \ 346 | $(AWK) ' { files[$$0] = 1; } \ 347 | END { for (i in files) print i; }'`; \ 348 | test -z "$(CTAGS_ARGS)$$tags$$unique" \ 349 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 350 | $$tags $$unique 351 | 352 | GTAGS: 353 | here=`$(am__cd) $(top_builddir) && pwd` \ 354 | && cd $(top_srcdir) \ 355 | && gtags -i $(GTAGS_ARGS) $$here 356 | 357 | distclean-tags: 358 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 359 | 360 | distdir: $(DISTFILES) 361 | $(am__remove_distdir) 362 | mkdir $(distdir) 363 | @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ 364 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ 365 | list='$(DISTFILES)'; for file in $$list; do \ 366 | case $$file in \ 367 | $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ 368 | $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ 369 | esac; \ 370 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 371 | dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ 372 | if test "$$dir" != "$$file" && test "$$dir" != "."; then \ 373 | dir="/$$dir"; \ 374 | $(mkdir_p) "$(distdir)$$dir"; \ 375 | else \ 376 | dir=''; \ 377 | fi; \ 378 | if test -d $$d/$$file; then \ 379 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 380 | cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ 381 | fi; \ 382 | cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ 383 | else \ 384 | test -f $(distdir)/$$file \ 385 | || cp -p $$d/$$file $(distdir)/$$file \ 386 | || exit 1; \ 387 | fi; \ 388 | done 389 | -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ 390 | ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ 391 | ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ 392 | ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ 393 | || chmod -R a+r $(distdir) 394 | dist-gzip: distdir 395 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 396 | $(am__remove_distdir) 397 | 398 | dist-bzip2: distdir 399 | tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 400 | $(am__remove_distdir) 401 | 402 | dist-tarZ: distdir 403 | tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z 404 | $(am__remove_distdir) 405 | 406 | dist-shar: distdir 407 | shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz 408 | $(am__remove_distdir) 409 | 410 | dist-zip: distdir 411 | -rm -f $(distdir).zip 412 | zip -rq $(distdir).zip $(distdir) 413 | $(am__remove_distdir) 414 | 415 | dist dist-all: distdir 416 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 417 | $(am__remove_distdir) 418 | 419 | # This target untars the dist file and tries a VPATH configuration. Then 420 | # it guarantees that the distribution is self-contained by making another 421 | # tarfile. 422 | distcheck: dist 423 | case '$(DIST_ARCHIVES)' in \ 424 | *.tar.gz*) \ 425 | GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ 426 | *.tar.bz2*) \ 427 | bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ 428 | *.tar.Z*) \ 429 | uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ 430 | *.shar.gz*) \ 431 | GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ 432 | *.zip*) \ 433 | unzip $(distdir).zip ;;\ 434 | esac 435 | chmod -R a-w $(distdir); chmod a+w $(distdir) 436 | mkdir $(distdir)/_build 437 | mkdir $(distdir)/_inst 438 | chmod a-w $(distdir) 439 | dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ 440 | && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ 441 | && cd $(distdir)/_build \ 442 | && ../configure --srcdir=.. --prefix="$$dc_install_base" \ 443 | $(DISTCHECK_CONFIGURE_FLAGS) \ 444 | && $(MAKE) $(AM_MAKEFLAGS) \ 445 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ 446 | && $(MAKE) $(AM_MAKEFLAGS) check \ 447 | && $(MAKE) $(AM_MAKEFLAGS) install \ 448 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ 449 | && $(MAKE) $(AM_MAKEFLAGS) uninstall \ 450 | && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ 451 | distuninstallcheck \ 452 | && chmod -R a-w "$$dc_install_base" \ 453 | && ({ \ 454 | (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ 455 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ 456 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ 457 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ 458 | distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ 459 | } || { rm -rf "$$dc_destdir"; exit 1; }) \ 460 | && rm -rf "$$dc_destdir" \ 461 | && $(MAKE) $(AM_MAKEFLAGS) dist \ 462 | && rm -rf $(DIST_ARCHIVES) \ 463 | && $(MAKE) $(AM_MAKEFLAGS) distcleancheck 464 | $(am__remove_distdir) 465 | @(echo "$(distdir) archives ready for distribution: "; \ 466 | list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ 467 | sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' 468 | distuninstallcheck: 469 | @cd $(distuninstallcheck_dir) \ 470 | && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ 471 | || { echo "ERROR: files left after uninstall:" ; \ 472 | if test -n "$(DESTDIR)"; then \ 473 | echo " (check DESTDIR support)"; \ 474 | fi ; \ 475 | $(distuninstallcheck_listfiles) ; \ 476 | exit 1; } >&2 477 | distcleancheck: distclean 478 | @if test '$(srcdir)' = . ; then \ 479 | echo "ERROR: distcleancheck can only run from a VPATH build" ; \ 480 | exit 1 ; \ 481 | fi 482 | @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ 483 | || { echo "ERROR: files left in build directory after distclean:" ; \ 484 | $(distcleancheck_listfiles) ; \ 485 | exit 1; } >&2 486 | check-am: all-am 487 | check: check-am 488 | all-am: Makefile $(PROGRAMS) $(SCRIPTS) config.h 489 | installdirs: 490 | for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \ 491 | test -z "$$dir" || $(mkdir_p) "$$dir"; \ 492 | done 493 | install: install-am 494 | install-exec: install-exec-am 495 | install-data: install-data-am 496 | uninstall: uninstall-am 497 | 498 | install-am: all-am 499 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 500 | 501 | installcheck: installcheck-am 502 | install-strip: 503 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 504 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 505 | `test -z '$(STRIP)' || \ 506 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 507 | mostlyclean-generic: 508 | 509 | clean-generic: 510 | 511 | distclean-generic: 512 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 513 | 514 | maintainer-clean-generic: 515 | @echo "This command is intended for maintainers to use" 516 | @echo "it deletes files that may require special tools to rebuild." 517 | clean: clean-am 518 | 519 | clean-am: clean-binPROGRAMS clean-generic mostlyclean-am 520 | 521 | distclean: distclean-am 522 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 523 | -rm -rf ./$(DEPDIR) 524 | -rm -f Makefile 525 | distclean-am: clean-am distclean-compile distclean-generic \ 526 | distclean-hdr distclean-tags 527 | 528 | dvi: dvi-am 529 | 530 | dvi-am: 531 | 532 | html: html-am 533 | 534 | info: info-am 535 | 536 | info-am: 537 | 538 | install-data-am: 539 | 540 | install-exec-am: install-binPROGRAMS install-binSCRIPTS 541 | 542 | install-info: install-info-am 543 | 544 | install-man: 545 | 546 | installcheck-am: 547 | 548 | maintainer-clean: maintainer-clean-am 549 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 550 | -rm -rf $(top_srcdir)/autom4te.cache 551 | -rm -rf ./$(DEPDIR) 552 | -rm -f Makefile 553 | maintainer-clean-am: distclean-am maintainer-clean-generic 554 | 555 | mostlyclean: mostlyclean-am 556 | 557 | mostlyclean-am: mostlyclean-compile mostlyclean-generic 558 | 559 | pdf: pdf-am 560 | 561 | pdf-am: 562 | 563 | ps: ps-am 564 | 565 | ps-am: 566 | 567 | uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ 568 | uninstall-info-am 569 | 570 | .PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ 571 | clean-binPROGRAMS clean-generic ctags dist dist-all dist-bzip2 \ 572 | dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \ 573 | distclean-compile distclean-generic distclean-hdr \ 574 | distclean-tags distcleancheck distdir distuninstallcheck dvi \ 575 | dvi-am html html-am info info-am install install-am \ 576 | install-binPROGRAMS install-binSCRIPTS install-data \ 577 | install-data-am install-exec install-exec-am install-info \ 578 | install-info-am install-man install-strip installcheck \ 579 | installcheck-am installdirs maintainer-clean \ 580 | maintainer-clean-generic mostlyclean mostlyclean-compile \ 581 | mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ 582 | uninstall-am uninstall-binPROGRAMS uninstall-binSCRIPTS \ 583 | uninstall-info-am 584 | 585 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 586 | # Otherwise a system limit (for SysV at least) may be exceeded. 587 | .NOEXPORT: 588 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a rewrite of Arto Salmi's 6809 simulator. Many changes 2 | have been made to it. This program remains licensed under the 3 | GNU General Public License. 4 | 5 | Input Files 6 | 7 | 8 | Machines 9 | 10 | The simulator now has the notion of different 'machines': 11 | which says what types of I/O devices are mapped into the 6809's 12 | address space and how they can be accessed. Adding support for 13 | a new machine is fairly easy. 14 | 15 | There are 3 builtin machine types at present. The default, 16 | called 'simple', assumes that you have a full 64KB of RAM, 17 | minus some input/output functions mapped at $FF00 (see I/O below). 18 | If you compile a program with gcc6809 with no special linker 19 | option, you'll get an S-record file that is suitable for running 20 | on this machine. The S-record file will include a vector table 21 | at $FFF0, with a reset vector that points to a _start function, 22 | which will call your main() function. When main returns, 23 | _start writes to an 'exit register' at $FF01, which the simulator 24 | interprets and causes it to stop. 25 | 26 | gcc6809 also has a builtin notion of which addresses are used 27 | for text and data. The simple machine enforces this and will 28 | "fault" on invalid accesses. 29 | 30 | The second machine is 'wpc', and is an emulation of the 31 | Williams Pinball Controller which was the impetus for me 32 | working on the compiler in the first place. 33 | 34 | The third machine, still in development, is called 'eon' 35 | (for Eight-O-Nine). It is similar to simple but has some 36 | more advanced I/O capabilities, like a larger memory space 37 | that can be paged in/out, and a disk emulation for programs 38 | that wants to have persistence. 39 | 40 | TODO : Would anyone be interested in a CoCo machine type? 41 | 42 | 43 | Faults 44 | 45 | 46 | Debugging 47 | 48 | The simulator supports interactive debugging similar to that 49 | provided by 'gdb'. 50 | 51 | b 52 | Set a breakpoint at the given address. 53 | 54 | bl 55 | List all breakpoints. 56 | 57 | c 58 | Continue running. 59 | 60 | d 61 | Delete a breakpoint/watchpoint. 62 | 63 | di 64 | Add a display expression. The value of the expression 65 | is display anytime the CPU breaks. 66 | 67 | h 68 | Display help. 69 | 70 | l 71 | List CPU instructions. 72 | 73 | me 74 | Measure the amount of time that a function named by 75 | takes. 76 | 77 | n 78 | Continue until the next instruction is reached. 79 | If the current instruction is a call, then 80 | the debugger resumes after control returns. 81 | 82 | p 83 | Print the value of an expression. See "Expressions" below. 84 | 85 | q 86 | Quit the simulator. 87 | 88 | re 89 | Reset the CPU/machine. 90 | 91 | runfor 92 | Continue but break after a certain period of (simulated) time. 93 | 94 | s 95 | Step one CPU instruction. 96 | 97 | set 98 | Sets the value of an internal variable or target memory. 99 | See "Expressions" below for details on the syntax. 100 | 101 | so 102 | Run a set of debugger commands from another file. 103 | The commands may start/stop the CPU. When the commands 104 | are finished, control returns to the previous input 105 | source (the file that called it, or the keyboard.) 106 | 107 | sym 108 | Load a symbol table file. Currently, the only format 109 | supported is an aslink map file. 110 | 111 | td 112 | Dump the last 256 instructions that were executed. 113 | 114 | wa 115 | Add a watchpoint. The CPU will break when the 116 | memory given by is modified. 117 | 118 | x 119 | Examine target memory at the address given. 120 | 121 | 122 | ----------------------------------------------------------------- 123 | 124 | Original README text from Arto: 125 | 126 | 127 | simple 6809 simulator under GPL licence 128 | 129 | NOTE! this software is beta stage, and has bugs. 130 | To compile it you should have 32-bit ANSI C complier. 131 | 132 | This simulator is missing all interrupt related SYNC, NMI Etc... 133 | 134 | I am currently busy with school, thus this is relased. 135 | if you have guestion or found something funny in my code please mail me. 136 | 137 | have fun! 138 | 139 | arto salmi asalmi@ratol.fi 140 | 141 | history: 142 | 143 | 2001-01-28 V1.0 original version 144 | 2001-02-15 V1.1 fixed str_scan function, fixed dasm _rel_???? code. 145 | 2001-06-19 V1.2 Added changes made by Joze Fabcic: 146 | - 6809's memory is initialized to zero 147 | - function dasm() had two bugs when using vc6.0 complier: 148 | - RDWORD macro used two ++ in same variable 149 | - _rel_byte address was wrong by 1. 150 | - after EXIT command, if invalid instruction is encountered, monitor is activated again 151 | - default file format is motorola S-record 152 | - monitor formatting 153 | 154 | 155 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define if building universal (internal helper macro) */ 4 | #undef AC_APPLE_UNIVERSAL_BUILD 5 | 6 | /* Use WPC address map */ 7 | #undef CONFIG_WPC 8 | 9 | /* Use 6309 extensions */ 10 | #undef H6309 11 | 12 | /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ 13 | #undef HAVE_DOPRNT 14 | 15 | /* Define to 1 if you have the `gettimeofday' function. */ 16 | #undef HAVE_GETTIMEOFDAY 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_INTTYPES_H 20 | 21 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 22 | to 0 otherwise. */ 23 | #undef HAVE_MALLOC 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #undef HAVE_MEMORY_H 27 | 28 | /* Define to 1 if you have the `memset' function. */ 29 | #undef HAVE_MEMSET 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #undef HAVE_NETINET_IN_H 33 | 34 | /* Use readline library */ 35 | #undef HAVE_READLINE 36 | 37 | /* Define to 1 if you have the `select' function. */ 38 | #undef HAVE_SELECT 39 | 40 | /* Define to 1 if you have the `socket' function. */ 41 | #undef HAVE_SOCKET 42 | 43 | /* Define to 1 if you have the header file. */ 44 | #undef HAVE_STDINT_H 45 | 46 | /* Define to 1 if you have the header file. */ 47 | #undef HAVE_STDLIB_H 48 | 49 | /* Define to 1 if you have the `strchr' function. */ 50 | #undef HAVE_STRCHR 51 | 52 | /* Define to 1 if you have the header file. */ 53 | #undef HAVE_STRINGS_H 54 | 55 | /* Define to 1 if you have the header file. */ 56 | #undef HAVE_STRING_H 57 | 58 | /* Define to 1 if you have the `strstr' function. */ 59 | #undef HAVE_STRSTR 60 | 61 | /* Define to 1 if you have the `strtoul' function. */ 62 | #undef HAVE_STRTOUL 63 | 64 | /* Define to 1 if you have the header file. */ 65 | #undef HAVE_SYS_SELECT_H 66 | 67 | /* Define to 1 if you have the header file. */ 68 | #undef HAVE_SYS_SOCKET_H 69 | 70 | /* Define to 1 if you have the header file. */ 71 | #undef HAVE_SYS_STAT_H 72 | 73 | /* Define to 1 if you have the header file. */ 74 | #undef HAVE_SYS_TIME_H 75 | 76 | /* Define to 1 if you have the header file. */ 77 | #undef HAVE_SYS_TYPES_H 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #undef HAVE_TERMIOS_H 81 | 82 | /* Define to 1 if you have the header file. */ 83 | #undef HAVE_UNISTD_H 84 | 85 | /* Define to 1 if you have the `vprintf' function. */ 86 | #undef HAVE_VPRINTF 87 | 88 | /* Name of package */ 89 | #undef PACKAGE 90 | 91 | /* Define to the address where bug reports for this package should be sent. */ 92 | #undef PACKAGE_BUGREPORT 93 | 94 | /* Define to the full name of this package. */ 95 | #undef PACKAGE_NAME 96 | 97 | /* Define to the full name and version of this package. */ 98 | #undef PACKAGE_STRING 99 | 100 | /* Define to the one symbol short name of this package. */ 101 | #undef PACKAGE_TARNAME 102 | 103 | /* Define to the version of this package. */ 104 | #undef PACKAGE_VERSION 105 | 106 | /* Define as the return type of signal handlers (`int' or `void'). */ 107 | #undef RETSIGTYPE 108 | 109 | /* Define to the type of arg 1 for `select'. */ 110 | #undef SELECT_TYPE_ARG1 111 | 112 | /* Define to the type of args 2, 3 and 4 for `select'. */ 113 | #undef SELECT_TYPE_ARG234 114 | 115 | /* Define to the type of arg 5 for `select'. */ 116 | #undef SELECT_TYPE_ARG5 117 | 118 | /* Define to 1 if you have the ANSI C header files. */ 119 | #undef STDC_HEADERS 120 | 121 | /* Define to 1 if you can safely include both and . */ 122 | #undef TIME_WITH_SYS_TIME 123 | 124 | /* Version number of package */ 125 | #undef VERSION 126 | 127 | /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most 128 | significant byte first (like Motorola and SPARC, unlike Intel). */ 129 | #if defined AC_APPLE_UNIVERSAL_BUILD 130 | # if defined __BIG_ENDIAN__ 131 | # define WORDS_BIGENDIAN 1 132 | # endif 133 | #else 134 | # ifndef WORDS_BIGENDIAN 135 | # undef WORDS_BIGENDIAN 136 | # endif 137 | #endif 138 | 139 | /* Define for Solaris 2.5.1 so the uint32_t typedef from , 140 | , or is not used. If the typedef were allowed, the 141 | #define below would cause a syntax error. */ 142 | #undef _UINT32_T 143 | 144 | /* Define for Solaris 2.5.1 so the uint8_t typedef from , 145 | , or is not used. If the typedef were allowed, the 146 | #define below would cause a syntax error. */ 147 | #undef _UINT8_T 148 | 149 | /* Define to empty if `const' does not conform to ANSI C. */ 150 | #undef const 151 | 152 | /* Define to `__inline__' or `__inline' if that's what the C compiler 153 | calls it, or to nothing if 'inline' is not supported under any name. */ 154 | #ifndef __cplusplus 155 | #undef inline 156 | #endif 157 | 158 | /* Define to rpl_malloc if the replacement function should be used. */ 159 | #undef malloc 160 | 161 | /* Define to the type of an unsigned integer type of width exactly 16 bits if 162 | such a type exists and the standard includes do not define it. */ 163 | #undef uint16_t 164 | 165 | /* Define to the type of an unsigned integer type of width exactly 32 bits if 166 | such a type exists and the standard includes do not define it. */ 167 | #undef uint32_t 168 | 169 | /* Define to the type of an unsigned integer type of width exactly 8 bits if 170 | such a type exists and the standard includes do not define it. */ 171 | #undef uint8_t 172 | 173 | /* Define to empty if the keyword `volatile' does not work. Warning: valid 174 | code using `volatile' can become incorrect without. Disable with care. */ 175 | #undef volatile 176 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ(2.61) 2 | AC_INIT(m6809-run, 0.92, brian@oddchange.com) 3 | AC_CONFIG_SRCDIR([6809.c]) 4 | AM_INIT_AUTOMAKE([foreign]) 5 | AC_CONFIG_HEADER([config.h]) 6 | 7 | # Checks for programs. 8 | AC_PROG_CC 9 | 10 | # Checks for header files. 11 | AC_HEADER_STDC 12 | AC_CHECK_HEADERS([netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h]) 13 | 14 | # Checks for typedefs, structures, and compiler characteristics. 15 | AC_C_BIGENDIAN 16 | AC_C_CONST 17 | AC_C_INLINE 18 | AC_HEADER_TIME 19 | AC_TYPE_UINT16_T 20 | AC_TYPE_UINT32_T 21 | AC_TYPE_UINT8_T 22 | AC_C_VOLATILE 23 | 24 | # Checks for library functions. 25 | AC_FUNC_MALLOC 26 | AC_FUNC_SELECT_ARGTYPES 27 | AC_TYPE_SIGNAL 28 | AC_FUNC_VPRINTF 29 | AC_CHECK_FUNCS([gettimeofday memset select strchr strstr strtoul socket]) 30 | 31 | AC_ARG_ENABLE([wpc], 32 | AC_HELP_STRING([--enable-wpc], [Enable WPC address map]), 33 | [wpc=$enableval], [wpc=no]) 34 | if test $wpc = yes; then 35 | AC_DEFINE(CONFIG_WPC, 1, [Use WPC address map]) 36 | fi 37 | 38 | AC_ARG_ENABLE([6309], 39 | AC_HELP_STRING([--enable-6309], [Enable 6309 extensions]), 40 | [h6309=$enableval], [h6309=no]) 41 | if test $h6309 = yes; then 42 | AC_DEFINE(H6309, 1, [Use 6309 extensions]) 43 | fi 44 | 45 | AC_ARG_ENABLE([readline], 46 | AC_HELP_STRING([--enable-readline], [Enable readline library]), 47 | [rl_lib=$enableval], [rl_lib=no]) 48 | if test $rl_lib = yes; then 49 | AC_DEFINE(HAVE_READLINE, 1, [Use readline library]) 50 | READLINE_LIBS="-L/lib -lreadline" 51 | AC_SUBST(READLINE_LIBS) 52 | fi 53 | 54 | AC_CONFIG_FILES([Makefile]) 55 | AC_OUTPUT 56 | -------------------------------------------------------------------------------- /disk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2006-2009 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include "machine.h" 23 | #include "eon.h" 24 | 25 | /* The disk drive is emulated as follows: 26 | * The disk is capable of "bus-mastering" and is able to dump data directly 27 | * into a RAM device, without CPU-involvement. (The pages do not even need to 28 | * be mapped.) A transaction is initiated with the following parameters: 29 | * 30 | * - address of RAM, aligned to 512 bytes, must reside in lower 32KB. 31 | * Thus there are 64 possible sector locations. 32 | * - address of disk sector, given as a 16-bit value. This allows for up to 33 | * a 32MB disk. 34 | * - direction, either to disk or from disk. 35 | * 36 | * Emulation is synchronous with respect to the CPU. TODO: this should use 37 | * interrupts and add real some latency. 38 | */ 39 | 40 | struct disk_geometry 41 | { 42 | unsigned int sectors_per_track; 43 | unsigned int tracks_per_cylinder; 44 | }; 45 | 46 | struct disk_priv 47 | { 48 | FILE *fp; 49 | struct hw_device *dev; 50 | unsigned long offset; 51 | struct hw_device *ramdev; 52 | unsigned int sectors; 53 | char *ram; 54 | 55 | unsigned int cycles_to_irq; 56 | struct hw_device *int_dev; 57 | unsigned int int_line; 58 | }; 59 | 60 | 61 | void disk_update (struct hw_device *dev) 62 | { 63 | /* Simulate the way that an actual disk would work. 64 | Induce some latency into the process. */ 65 | } 66 | 67 | U8 disk_read (struct hw_device *dev, unsigned long addr) 68 | { 69 | struct disk_priv *disk = (struct disk_priv *)dev->priv; 70 | } 71 | 72 | void disk_write (struct hw_device *dev, unsigned long addr, U8 val) 73 | { 74 | struct disk_priv *disk = (struct disk_priv *)dev->priv; 75 | 76 | switch (addr) 77 | { 78 | case DSK_ADDR: 79 | disk->ram = disk->ramdev->priv + val * SECTOR_SIZE; 80 | break; 81 | case DSK_SECTOR: 82 | disk->offset = val; /* high byte */ 83 | break; 84 | case DSK_SECTOR+1: /* low byte */ 85 | /* Note, only writes to the low byte cause an update. */ 86 | disk->offset = (disk->offset << 8) | val; 87 | disk->offset *= SECTOR_SIZE; 88 | fseek (disk->fp, disk->offset, SEEK_SET); 89 | break; 90 | case DSK_CTRL: 91 | if (val & DSK_READ) 92 | { 93 | fread (disk->ram, SECTOR_SIZE, 1, disk->fp); 94 | } 95 | else if (val & DSK_WRITE) 96 | { 97 | fwrite (disk->ram, SECTOR_SIZE, 1, disk->fp); 98 | } 99 | else if (val & DSK_ERASE) 100 | { 101 | char empty_sector[SECTOR_SIZE]; 102 | memset (empty_sector, 0xff, SECTOR_SIZE); 103 | fwrite (empty_sector, SECTOR_SIZE, 1, disk->fp); 104 | } 105 | 106 | if (val & DSK_FLUSH) 107 | { 108 | fflush (disk->fp); 109 | } 110 | break; 111 | } 112 | } 113 | 114 | void disk_reset (struct hw_device *dev) 115 | { 116 | //struct disk_priv *disk = (struct disk_priv *)dev->priv; 117 | disk_write (dev, DSK_ADDR, 0); 118 | disk_write (dev, DSK_SECTOR, 0); 119 | disk_write (dev, DSK_SECTOR+1, 0); 120 | disk_write (dev, DSK_CTRL, DSK_FLUSH); 121 | } 122 | 123 | void disk_format (struct hw_device *dev) 124 | { 125 | unsigned int sector; 126 | struct disk_priv *disk = (struct disk_priv *)dev->priv; 127 | 128 | for (sector = 0; sector < disk->sectors; sector++) 129 | { 130 | disk_write (dev, DSK_SECTOR, sector >> 8); 131 | disk_write (dev, DSK_SECTOR+1, sector & 0xFF); 132 | disk_write (dev, DSK_CTRL, DSK_ERASE); 133 | } 134 | disk_write (dev, DSK_CTRL, DSK_FLUSH); 135 | } 136 | 137 | struct hw_class disk_class = 138 | { 139 | .readonly = 0, 140 | .reset = disk_reset, 141 | .read = disk_read, 142 | .write = disk_write, 143 | .update = disk_update, 144 | }; 145 | 146 | struct hw_device *disk_create (const char *backing_file, 147 | struct hw_device *ram_dev) 148 | { 149 | struct disk_priv *disk = malloc (sizeof (struct disk_priv)); 150 | int newdisk = 0; 151 | 152 | disk->fp = file_open (NULL, backing_file, "r+b"); 153 | if (disk->fp == NULL) 154 | { 155 | printf ("warning: disk does not exist, creating\n"); 156 | disk->fp = file_open (NULL, backing_file, "w+b"); 157 | newdisk = 1; 158 | if (disk->fp == NULL) 159 | { 160 | printf ("warning: disk not created\n"); 161 | } 162 | } 163 | 164 | disk->ram = 0; 165 | disk->ramdev = ram_dev; 166 | disk->dev = device_attach (&disk_class, 4, disk); 167 | disk->sectors = DISK_SECTOR_COUNT; 168 | disk->cycles_to_irq = 0; 169 | 170 | if (newdisk) 171 | disk_format (disk->dev); 172 | 173 | return disk->dev; 174 | } 175 | 176 | -------------------------------------------------------------------------------- /eon.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "machine.h" 4 | #include "eon.h" 5 | 6 | extern int system_running; 7 | 8 | 9 | void eon_fault (unsigned int addr, unsigned char type) 10 | { 11 | if (system_running) 12 | { 13 | sim_error (">>> Page fault: addr=%04X type=%02X PC=%04X\n", addr, type, get_pc ()); 14 | #if 0 15 | fault_addr = addr; 16 | fault_type = type; 17 | irq (); 18 | #endif 19 | } 20 | } 21 | 22 | 23 | /** 24 | * Initialize the EON machine. 25 | */ 26 | void eon_init (const char *boot_rom_file) 27 | { 28 | struct hw_device *dev, *ram_dev; 29 | 30 | /* The MMU must be defined first, as all other devices 31 | that are attached can try to hook into the MMU. */ 32 | device_define ( mmu_create (), 0, 33 | MMU_ADDR, BUS_MAP_SIZE, MAP_READWRITE+MAP_FIXED ); 34 | 35 | /* A 1MB RAM part is mapped into all of the allowable 64KB 36 | address space, until overriden by other devices. */ 37 | device_define ( ram_dev = ram_create (RAM_SIZE), 0, 38 | 0x0000, MAX_CPU_ADDR, MAP_READWRITE ); 39 | 40 | device_define ( rom_create (boot_rom_file, BOOT_ROM_SIZE), 0, 41 | BOOT_ROM_ADDR, BOOT_ROM_SIZE, MAP_READABLE ); 42 | 43 | device_define ( dev = console_create (), 0, 44 | CONSOLE_ADDR, BUS_MAP_SIZE, MAP_READWRITE ); 45 | device_define (dev, 0, 46 | 0xFF00, BUS_MAP_SIZE, MAP_READWRITE ); 47 | 48 | device_define ( disk_create ("disk.bin", ram_dev), 0, 49 | DISK_ADDR(0), BUS_MAP_SIZE, MAP_READWRITE); 50 | } 51 | 52 | 53 | /* 54 | * Initialize the second-generation EON machine (EON2). 55 | */ 56 | void eon2_init (const char *boot_rom_file) 57 | { 58 | struct hw_device *dev, *ram_dev, *mmudev, *iodev, *intdev; 59 | 60 | /* Create a 1MB RAM */ 61 | ram_dev = ram_create (0x100000); 62 | 63 | /* Place the RAM behind a small MMU, which dynamically remaps 64 | portions of the RAM into the processor address space */ 65 | mmudev = small_mmu_create (ram_dev); 66 | 67 | /* Create and map in the ROM */ 68 | dev = rom_create (boot_rom_file, 0x800); 69 | device_define (dev, 0, 0xF800, 0x0800, MAP_READABLE); 70 | 71 | /* Create an I/O expander to hold all of the I/O registers. 72 | Each device is allocated only 8 bytes. */ 73 | iodev = ioexpand_create (); 74 | device_define (iodev, 0, 0xFF00, 128, MAP_READWRITE); 75 | ioexpand_attach (iodev, 0, serial_create ()); 76 | ioexpand_attach (iodev, 1, disk_create ("disk.bin", ram_dev)); 77 | ioexpand_attach (iodev, 2, mmudev); 78 | ioexpand_attach (iodev, 3, intdev = imux_create (1)); 79 | /* 4 = config EEPROM */ 80 | /* 5 = video display */ 81 | /* 6 = battery-backed clock */ 82 | /* 7 = power control (reboot/off) */ 83 | /* 8 = periodic timer/oscillator */ 84 | /* 9 = hostfile (for debug only) */ 85 | ioexpand_attach (iodev, 9, hostfile_create ("hostfile", O_RDWR)); 86 | /* etc. up to device 15 */ 87 | /* May need to define an I/O _multiplexer_ to support more than 16 devices */ 88 | 89 | dev = oscillator_create (intdev, 0); 90 | } 91 | 92 | 93 | /** 94 | * Initialize the simple machine, which is the default 95 | * machine that has no bells or whistles. 96 | */ 97 | void simple_init (const char *boot_rom_file) 98 | { 99 | device_define ( ram_create (MAX_CPU_ADDR), 0, 100 | 0x0000, MAX_CPU_ADDR, MAP_READWRITE ); 101 | device_define ( console_create (), 0, 102 | 0xFF00, BUS_MAP_SIZE, MAP_READWRITE ); 103 | } 104 | 105 | 106 | struct machine eon_machine = 107 | { 108 | .name = "eon", 109 | .fault = eon_fault, 110 | .init = eon_init, 111 | .periodic = 0, 112 | }; 113 | 114 | struct machine eon2_machine = 115 | { 116 | .name = "eon2", 117 | .fault = eon_fault, 118 | .init = eon2_init, 119 | .periodic = 0, 120 | }; 121 | 122 | struct machine simple_machine = 123 | { 124 | .name = "simple", 125 | .fault = eon_fault, 126 | .init = simple_init, 127 | .periodic = 0, 128 | }; 129 | 130 | 131 | -------------------------------------------------------------------------------- /eon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2008 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef _MACHINE_EON_H 22 | #define _MACHINE_EON_H 23 | 24 | /* This file defines the characteristics of the EON machine architecture. 25 | EON is a little more advanced than the 'simple' architecture that runs by 26 | default, and can be used to run more sophiscated programs for the 6809. 27 | However, no actual hardware resembling this exists. 28 | 29 | The computer has a total of 1MB of RAM, which is mapped to logical address 30 | 0x0000. As the 6809 only has 64KB addressable at a time, some bank 31 | switching is required. The address space is defined into 16, 4KB pages. 32 | The pages from 0xE000-0xFFFF are special, though, and allow access to 33 | I/O and a read-only boot ROM. Thus, pages 0-13 can be mapped to any 34 | of the 1MB RAM, page 14 has all of the I/O registers and some of the boot 35 | ROM, and page 15 has the remaining boot ROM, including interrupt vectors. 36 | The boot ROM file to use is specified as a command-line option to the 37 | emulator. 38 | 39 | Each I/O device comprises 128 bytes of address space. There can be up 40 | to a maximum of 8 devices defined this way. The "device ID" is just the 41 | offset from the beginning of the I/O region. At present, 5 devices are 42 | defined: 43 | 44 | Device 0 - the MMU. This provides registers for reprogramming the paging 45 | hardware. 46 | 47 | Device 1 - the power manager. This is not yet implemented. 48 | 49 | Device 2 - the console. This has the basic stdin/stdout, akin to a serial 50 | port. 51 | 52 | Device 3 - the display. Not implemented yet, this would be akin to a 53 | graphical interface. 54 | 55 | Device 4 - the disk drive. See machine.c for a full description of how the 56 | disk works. EON simulates the disk using a file named 'disk.bin', so its 57 | contents are actually persistent. Disk transfers conceptually DMA to/from 58 | RAM in 512-byte chunks. The maximum disk size is 32MB (16-bit sector numbers). 59 | 60 | */ 61 | 62 | /* RAM */ 63 | #define RAM_SIZE 0x100000 64 | 65 | /* I/O regions (1KB) */ 66 | #define BOOT_IO_ADDR 0xE000 67 | #define DEVICE_BASE(n) (BOOT_IO_ADDR + (BUS_MAP_SIZE * (n))) 68 | 69 | /* The MMU */ 70 | 71 | #define MMU_DEVID 0 72 | #define MMU_ADDR DEVICE_BASE(MMU_DEVID) 73 | #define MMU_PAGESIZE 4096 74 | #define MMU_PAGECOUNT (MAX_CPU_ADDR / MMU_PAGESIZE) 75 | #define MMU_PAGEREGS 4 76 | 77 | /* device select */ 78 | #define MMU_DEV(p) (MMU_ADDR + ((p) * MMU_PAGEREGS) + 0) 79 | /* 4KB region to map in */ 80 | #define MMU_OFF(p) (MMU_ADDR + ((p) * MMU_PAGEREGS) + 1) 81 | /* permissions */ 82 | #define MMU_FLG(p) (MMU_ADDR + ((p) * MMU_PAGEREGS) + 2) 83 | 84 | #define MMU_FAULT_ADDR (MMU_ADDR + 0x60) 85 | #define MMU_FAULT_TYPE (MMU_ADDR + 0x62) 86 | 87 | /* The Power Manager */ 88 | 89 | #define POWERMGR_DEVID 1 90 | #define POWERMGR_ADDR DEVICE_BASE(POWERMGR_DEVID) 91 | #define POWER_CTRL (POWERMGR_ADDR + 0) 92 | #define POWER_RESET_REG (POWERMGMT_ADDR + 1) 93 | 94 | /* The Console */ 95 | 96 | #define CONSOLE_DEVID 2 97 | #define CONSOLE_ADDR DEVICE_BASE(CONSOLE_DEVID) 98 | #define CONSOLE_OUT (CONSOLE_ADDR + 0) 99 | #define LEGACY_EXIT (CONSOLE_ADDR + 1) 100 | #define CONSOLE_IN (CONSOLE_ADDR + 2) 101 | 102 | #define CON_OUT 0 103 | #define CON_EXIT 1 104 | #define CON_IN 2 105 | 106 | /* The Display */ 107 | 108 | #define DISPLAY_DEVID 3 109 | #define DISPLAY_ADDR DEVICE_BASE(DISPLAY_DEVID) 110 | 111 | /* The Disk Drive */ 112 | 113 | #define DISK0_DEVID 4 114 | #define DISK_ADDR(n) DEVICE_BASE(DISK0_DEVID + (n)) 115 | #define DISK_SECTOR_COUNT 65536 116 | #define SECTOR_SIZE 512 117 | 118 | #define DSK_CTRL 0 119 | #define DSK_READ 0x1 120 | #define DSK_WRITE 0x2 121 | #define DSK_FLUSH 0x4 122 | #define DSK_ERASE 0x8 123 | #define DSK_ADDR 1 124 | #define DSK_SECTOR 2 /* and 3 */ 125 | 126 | /* The Interrupt Multiplexer */ 127 | 128 | #define IMUX_DEVID 5 129 | #define IMUX_ADDR DEVICE_BASE(IMUX_DEVID) 130 | 131 | #define IMUX_ENB 0 132 | #define IMUX_PEND 1 133 | 134 | /* Boot ROM region (7KB) */ 135 | #define BOOT_ROM_ADDR 0xE400 136 | #define BOOT_ROM_SIZE 0x1C00 137 | 138 | #endif /* _MACHINE_EON_H */ 139 | -------------------------------------------------------------------------------- /fileio.c: -------------------------------------------------------------------------------- 1 | 2 | #include "6809.h" 3 | 4 | void 5 | path_init (struct pathlist *path) 6 | { 7 | path->count = 0; 8 | } 9 | 10 | void 11 | path_add (struct pathlist *path, const char *dir) 12 | { 13 | char *dir2; 14 | dir2 = path->entry[path->count++] = malloc (strlen (dir) + 1); 15 | strcpy (dir2, dir); 16 | } 17 | 18 | 19 | FILE * 20 | file_open (struct pathlist *path, const char *filename, const char *mode) 21 | { 22 | FILE *fp; 23 | char fqname[128]; 24 | int count; 25 | const char dirsep = '/'; 26 | 27 | fp = fopen (filename, mode); 28 | if (fp) 29 | return fp; 30 | 31 | if (!path || strchr (filename, dirsep) || *mode == 'w') 32 | return NULL; 33 | 34 | for (count = 0; count < path->count; count++) 35 | { 36 | sprintf (fqname, "%s%c%s", path->entry[count], dirsep, filename); 37 | fp = fopen (fqname, mode); 38 | if (fp) 39 | return fp; 40 | } 41 | 42 | return NULL; 43 | } 44 | 45 | 46 | FILE * 47 | file_require_open (struct pathlist *path, const char *filename, const char *mode) 48 | { 49 | FILE *fp = file_open (path, filename, mode); 50 | if (!fp) 51 | fprintf (stderr, "error: could not open '%s'\n", filename); 52 | return fp; 53 | } 54 | 55 | 56 | void 57 | file_close (FILE *fp) 58 | { 59 | fclose (fp); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /imux.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* The interrupt multiplexer */ 22 | 23 | #include "machine.h" 24 | #include "eon.h" 25 | 26 | struct imux 27 | { 28 | unsigned int in_use; /* Bits for each int that are used */ 29 | unsigned int enabled; /* Bits for each int that is enabled */ 30 | unsigned int pending; /* Bits for each int that are active */ 31 | unsigned int src; /* Source line back to CPU */ 32 | }; 33 | 34 | 35 | /* 36 | * Refresh the state of the interrupt line back to the CPU. 37 | * src == 1 refers to IRQ, src == 2 for FIRQ. 38 | */ 39 | void imux_refresh (struct imux *mux) 40 | { 41 | if (mux->pending & mux->enabled) 42 | { 43 | if (mux->src == 1) 44 | request_irq (mux->src); 45 | else 46 | request_firq (mux->src); 47 | } 48 | else 49 | { 50 | if (mux->src == 1) 51 | release_irq (mux->src); 52 | else 53 | release_firq (mux->src); 54 | } 55 | } 56 | 57 | 58 | void imux_reset (struct hw_device *dev) 59 | { 60 | struct imux *mux = (struct imux *)dev->priv; 61 | mux->enabled = 0; 62 | mux->pending = 0; 63 | } 64 | 65 | U8 imux_read (struct hw_device *dev, unsigned long addr) 66 | { 67 | struct imux *mux = (struct imux *)dev->priv; 68 | switch (addr) 69 | { 70 | case IMUX_ENB: 71 | /* Return the enable bits */ 72 | return mux->enabled & 0xFF; 73 | 74 | case IMUX_PEND: 75 | /* Return the pending bits */ 76 | return mux->pending & 0xFF; 77 | } 78 | return -1; 79 | } 80 | 81 | 82 | void imux_write (struct hw_device *dev, unsigned long addr, U8 val) 83 | { 84 | struct imux *mux = (struct imux *)dev->priv; 85 | switch (addr) 86 | { 87 | case IMUX_ENB: 88 | /* Set the interrupt enables */ 89 | mux->enabled = val; 90 | break; 91 | case IMUX_PEND: 92 | /* Clear pending interrupt source */ 93 | mux->pending &= ~val; 94 | break; 95 | } 96 | imux_refresh (mux); 97 | } 98 | 99 | /* 100 | * Register an interrupt line with the multiplexer. 101 | * This just tracks which ones are in use. 102 | */ 103 | void imux_register (struct hw_device *dev, unsigned int sig) 104 | { 105 | struct imux *mux = (struct imux *)dev->priv; 106 | mux->in_use |= (1 << sig); 107 | } 108 | 109 | /* 110 | * Assert an edge-triggered interrupt line. 111 | */ 112 | void imux_assert (struct hw_device *dev, unsigned int sig) 113 | { 114 | struct imux *mux = (struct imux *)dev->priv; 115 | mux->pending |= (1 << sig); 116 | imux_refresh (mux); 117 | } 118 | 119 | 120 | struct hw_class imux_class = 121 | { 122 | .readonly = 0, 123 | .reset = imux_reset, 124 | .read = imux_read, 125 | .write = imux_write, 126 | }; 127 | 128 | struct hw_device *imux_create (unsigned int cpu_line) 129 | { 130 | struct imux *imux = malloc (sizeof (struct imux)); 131 | imux->src = cpu_line; 132 | return device_attach (&imux_class, BUS_MAP_SIZE, imux); 133 | } 134 | 135 | 136 | -------------------------------------------------------------------------------- /ioexpand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include 23 | #include "machine.h" 24 | 25 | /* An I/O expander allows a single, 128-byte region to be shared among multiple 26 | devices. It subdivides the region into 16 8-byte subdevices. It is needed 27 | to work around the inability of the system bus to handle attaching devices 28 | less than 128 bytes wide. */ 29 | 30 | #define NR_IOEXPAND 16 31 | #define IO_WINDOW 8 32 | 33 | struct ioexpand 34 | { 35 | struct hw_device *ios[NR_IOEXPAND]; 36 | }; 37 | 38 | 39 | void ioexpand_attach (struct hw_device *expander_dev, int slot, struct hw_device *io_dev) 40 | { 41 | struct ioexpand *iom = (struct ioexpand *)expander_dev->priv; 42 | iom->ios[slot] = io_dev; 43 | } 44 | 45 | void ioexpand_reset (struct hw_device *dev) 46 | { 47 | int i; 48 | struct ioexpand *iom = (struct ioexpand *)dev->priv; 49 | 50 | /* Propagate the reset to all devices behind the expander */ 51 | for (i=0; i < NR_IOEXPAND; i++) 52 | if ((dev = iom->ios[i]) != NULL) 53 | dev->class_ptr->reset (dev); 54 | } 55 | 56 | U8 ioexpand_read (struct hw_device *dev, unsigned long addr) 57 | { 58 | struct ioexpand *iom = (struct ioexpand *)dev->priv; 59 | dev = iom->ios[addr / IO_WINDOW]; 60 | if (!dev) 61 | sim_error ("expander read from %04X has no backing device\n", addr); 62 | return dev->class_ptr->read (dev, addr % IO_WINDOW); 63 | } 64 | 65 | void ioexpand_write (struct hw_device *dev, unsigned long addr, U8 val) 66 | { 67 | struct ioexpand *iom = (struct ioexpand *)dev->priv; 68 | dev = iom->ios[addr / IO_WINDOW]; 69 | if (!dev) 70 | sim_error ("expander write %02X to %04X has no backing device\n", val, addr); 71 | dev->class_ptr->write (dev, addr % IO_WINDOW, val); 72 | } 73 | 74 | struct hw_class ioexpand_class = 75 | { 76 | .readonly = 0, 77 | .reset = ioexpand_reset, 78 | .read = ioexpand_read, 79 | .write = ioexpand_write, 80 | }; 81 | 82 | struct hw_device *ioexpand_create (void) 83 | { 84 | int i; 85 | struct ioexpand *iom = malloc (sizeof (struct ioexpand)); 86 | for (i=0; i < NR_IOEXPAND; i++) 87 | iom->ios[i] = NULL; 88 | return device_attach (&ioexpand_class, BUS_MAP_SIZE, iom); 89 | } 90 | -------------------------------------------------------------------------------- /machine.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2008 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include "machine.h" 26 | #include "6809.h" 27 | #include "eon.h" 28 | 29 | #define CONFIG_LEGACY 30 | #define MISSING 0xff 31 | #define mmu_device (device_table[0]) 32 | 33 | extern void eon_init (const char *); 34 | extern void wpc_init (const char *); 35 | 36 | struct machine *machine; 37 | 38 | unsigned int device_count = 0; 39 | struct hw_device *device_table[MAX_BUS_DEVICES]; 40 | 41 | struct hw_device *null_device; 42 | 43 | struct bus_map busmaps[NUM_BUS_MAPS]; 44 | 45 | struct bus_map default_busmaps[NUM_BUS_MAPS]; 46 | 47 | U16 fault_addr; 48 | 49 | U8 fault_type; 50 | 51 | int system_running = 0; 52 | 53 | 54 | void cpu_is_running (void) 55 | { 56 | system_running = 1; 57 | } 58 | 59 | void do_fault (unsigned int addr, unsigned int type) 60 | { 61 | if (system_running) 62 | machine->fault (addr, type); 63 | } 64 | 65 | 66 | void exit_fault (unsigned int addr, unsigned int type) 67 | { 68 | monitor_on = debug_enabled; 69 | sim_error ("Fault: addr=%04X type=%02X\n", addr, type); 70 | exit (1); 71 | } 72 | 73 | 74 | /** 75 | * Attach a new device to the bus. Only called during init. 76 | */ 77 | struct hw_device *device_attach (struct hw_class *class_ptr, unsigned int size, void *priv) 78 | { 79 | struct hw_device *dev = malloc (sizeof (struct hw_device)); 80 | dev->class_ptr = class_ptr; 81 | dev->devid = device_count; 82 | dev->size = size; 83 | dev->priv = priv; 84 | device_table[device_count++] = dev; 85 | 86 | /* Attach implies reset */ 87 | class_ptr->reset (dev); 88 | return dev; 89 | }; 90 | 91 | 92 | /** 93 | * Map a portion of a device into the CPU's address space. 94 | */ 95 | void bus_map (unsigned int addr, 96 | unsigned int devid, 97 | unsigned long offset, 98 | unsigned int len, 99 | unsigned int flags) 100 | { 101 | struct bus_map *map; 102 | unsigned int start, count; 103 | 104 | /* Warn if trying to map too much */ 105 | if (addr + len > MAX_CPU_ADDR) 106 | { 107 | fprintf (stderr, "warning: mapping %04X bytes into %04X causes overflow\n", 108 | len, addr); 109 | } 110 | 111 | /* Round address and length to be multiples of the map unit size. */ 112 | addr = ((addr + BUS_MAP_SIZE - 1) / BUS_MAP_SIZE) * BUS_MAP_SIZE; 113 | len = ((len + BUS_MAP_SIZE - 1) / BUS_MAP_SIZE) * BUS_MAP_SIZE; 114 | offset = ((offset + BUS_MAP_SIZE - 1) / BUS_MAP_SIZE) * BUS_MAP_SIZE; 115 | 116 | /* Convert from byte addresses to unit counts */ 117 | start = addr / BUS_MAP_SIZE; 118 | count = len / BUS_MAP_SIZE; 119 | 120 | /* Initialize the maps. This will let the CPU access the device. */ 121 | map = &busmaps[start]; 122 | while (count > 0) 123 | { 124 | if (!(map->flags & MAP_FIXED)) 125 | { 126 | map->devid = devid; 127 | map->offset = offset; 128 | map->flags = flags; 129 | } 130 | count--; 131 | map++; 132 | offset += BUS_MAP_SIZE; 133 | } 134 | } 135 | 136 | void device_define (struct hw_device *dev, 137 | unsigned long offset, 138 | unsigned int addr, 139 | unsigned int len, 140 | unsigned int flags) 141 | { 142 | /* Note: len must be a multiple of BUS_MAP_SIZE */ 143 | bus_map (addr, dev->devid, offset, len, flags); 144 | } 145 | 146 | 147 | void bus_unmap (unsigned int addr, unsigned int len) 148 | { 149 | struct bus_map *map; 150 | unsigned int start, count; 151 | 152 | /* Round address and length to be multiples of the map unit size. */ 153 | addr = ((addr + BUS_MAP_SIZE - 1) / BUS_MAP_SIZE) * BUS_MAP_SIZE; 154 | len = ((len + BUS_MAP_SIZE - 1) / BUS_MAP_SIZE) * BUS_MAP_SIZE; 155 | 156 | /* Convert from byte addresses to unit counts */ 157 | start = addr / BUS_MAP_SIZE; 158 | count = len / BUS_MAP_SIZE; 159 | 160 | /* Set the maps to their defaults. */ 161 | memcpy (&busmaps[start], &default_busmaps[start], 162 | sizeof (struct bus_map) * count); 163 | } 164 | 165 | 166 | /** 167 | * Generate a page fault. ADDR says which address was accessed 168 | * incorrectly. TYPE says what kind of violation occurred. 169 | */ 170 | 171 | static struct bus_map *find_map (unsigned int addr) 172 | { 173 | return &busmaps[addr / BUS_MAP_SIZE]; 174 | } 175 | 176 | static struct hw_device *find_device (unsigned int addr, unsigned char id) 177 | { 178 | /* Fault if any invalid device is accessed */ 179 | if ((id == INVALID_DEVID) || (id >= device_count)) 180 | { 181 | do_fault (addr, FAULT_NO_RESPONSE); 182 | return null_device; 183 | } 184 | return device_table[id]; 185 | } 186 | 187 | 188 | void 189 | print_device_name (unsigned int devno) 190 | { 191 | struct hw_device *dev = device_table[devno]; 192 | printf ("%02X", devno); 193 | } 194 | 195 | 196 | absolute_address_t 197 | absolute_from_reladdr (unsigned int device, unsigned long reladdr) 198 | { 199 | return (device * 0x10000000L) + reladdr; 200 | } 201 | 202 | 203 | U8 abs_read8 (absolute_address_t addr) 204 | { 205 | unsigned int id = addr >> 28; 206 | unsigned long phy_addr = addr & 0xFFFFFFF; 207 | struct hw_device *dev = device_table[id]; 208 | struct hw_class *class_ptr = dev->class_ptr; 209 | return (*class_ptr->read) (dev, phy_addr); 210 | } 211 | 212 | 213 | /** 214 | * Called by the CPU to read a byte. 215 | * This is the bottleneck in terms of performance. Consider 216 | * a caching scheme that cuts down on some of this. 217 | * There is also a 16-bit version that is more efficient when 218 | * a full word is needed, but it implies that no reads will ever 219 | * occur across a device boundary. 220 | */ 221 | U8 cpu_read8 (unsigned int addr) 222 | { 223 | struct bus_map *map = find_map (addr); 224 | struct hw_device *dev = find_device (addr, map->devid); 225 | struct hw_class *class_ptr = dev->class_ptr; 226 | unsigned long phy_addr = map->offset + addr % BUS_MAP_SIZE; 227 | 228 | if (system_running && !(map->flags & MAP_READABLE)) 229 | machine->fault (addr, FAULT_NOT_READABLE); 230 | command_read_hook (absolute_from_reladdr (map->devid, phy_addr)); 231 | return (*class_ptr->read) (dev, phy_addr); 232 | } 233 | 234 | U16 cpu_read16 (unsigned int addr) 235 | { 236 | struct bus_map *map = find_map (addr); 237 | struct hw_device *dev = find_device (addr, map->devid); 238 | struct hw_class *class_ptr = dev->class_ptr; 239 | unsigned long phy_addr = map->offset + addr % BUS_MAP_SIZE; 240 | 241 | if (system_running && !(map->flags & MAP_READABLE)) 242 | do_fault (addr, FAULT_NOT_READABLE); 243 | command_read_hook (absolute_from_reladdr (map->devid, phy_addr)); 244 | return ((*class_ptr->read) (dev, phy_addr) << 8) 245 | | (*class_ptr->read) (dev, phy_addr+1); 246 | } 247 | 248 | 249 | /** 250 | * Called by the CPU to write a byte. 251 | */ 252 | void cpu_write8 (unsigned int addr, U8 val) 253 | { 254 | struct bus_map *map = find_map (addr); 255 | struct hw_device *dev = find_device (addr, map->devid); 256 | struct hw_class *class_ptr = dev->class_ptr; 257 | unsigned long phy_addr = map->offset + addr % BUS_MAP_SIZE; 258 | 259 | if (system_running && !(map->flags & MAP_WRITABLE)) 260 | do_fault (addr, FAULT_NOT_WRITABLE); 261 | (*class_ptr->write) (dev, phy_addr, val); 262 | command_write_hook (absolute_from_reladdr (map->devid, phy_addr), val); 263 | } 264 | 265 | void abs_write8 (absolute_address_t addr, U8 val) 266 | { 267 | unsigned int id = addr >> 28; 268 | unsigned long phy_addr = addr & 0xFFFFFFF; 269 | struct hw_device *dev = device_table[id]; 270 | struct hw_class *class_ptr = dev->class_ptr; 271 | class_ptr->write (dev, phy_addr, val); 272 | } 273 | 274 | 275 | 276 | absolute_address_t 277 | to_absolute (unsigned long cpuaddr) 278 | { 279 | struct bus_map *map = find_map (cpuaddr); 280 | struct hw_device *dev = find_device (cpuaddr, map->devid); 281 | unsigned long phy_addr = map->offset + cpuaddr % BUS_MAP_SIZE; 282 | return absolute_from_reladdr (map->devid, phy_addr); 283 | } 284 | 285 | 286 | void dump_machine (void) 287 | { 288 | unsigned int mapno; 289 | unsigned int n; 290 | 291 | for (mapno = 0; mapno < NUM_BUS_MAPS; mapno++) 292 | { 293 | struct bus_map *map = &busmaps[mapno]; 294 | printf ("Map %d addr=%04X dev=%d offset=%04X size=%06X flags=%02X\n", 295 | mapno, mapno * BUS_MAP_SIZE, map->devid, map->offset, 296 | 0 /* device_table[map->devid]->size */, map->flags); 297 | 298 | #if 0 299 | for (n = 0; n < BUS_MAP_SIZE; n++) 300 | printf ("%02X ", cpu_read8 (mapno * BUS_MAP_SIZE + n)); 301 | printf ("\n"); 302 | #endif 303 | } 304 | } 305 | 306 | 307 | /**********************************************************/ 308 | 309 | void null_reset (struct hw_device *dev) 310 | { 311 | } 312 | 313 | U8 null_read (struct hw_device *dev, unsigned long addr) 314 | { 315 | return 0xFF; 316 | } 317 | 318 | void null_write (struct hw_device *dev, unsigned long addr, U8 val) 319 | { 320 | } 321 | 322 | struct hw_class null_class = 323 | { 324 | .readonly = 0, 325 | .reset = null_reset, 326 | .read = null_read, 327 | .write = null_write, 328 | }; 329 | 330 | struct hw_device *null_create (void) 331 | { 332 | return device_attach (&null_class, 0, NULL); 333 | } 334 | 335 | 336 | /**********************************************************/ 337 | 338 | void ram_reset (struct hw_device *dev) 339 | { 340 | memset (dev->priv, 0, dev->size); 341 | } 342 | 343 | U8 ram_read (struct hw_device *dev, unsigned long addr) 344 | { 345 | char *buf = dev->priv; 346 | return buf[addr]; 347 | } 348 | 349 | void ram_write (struct hw_device *dev, unsigned long addr, U8 val) 350 | { 351 | char *buf = dev->priv; 352 | buf[addr] = val; 353 | } 354 | 355 | struct hw_class ram_class = 356 | { 357 | .readonly = 0, 358 | .reset = ram_reset, 359 | .read = ram_read, 360 | .write = ram_write, 361 | }; 362 | 363 | struct hw_device *ram_create (unsigned long size) 364 | { 365 | void *buf = malloc (size); 366 | return device_attach (&ram_class, size, buf); 367 | } 368 | 369 | /**********************************************************/ 370 | 371 | struct hw_class rom_class = 372 | { 373 | .readonly = 1, 374 | .reset = null_reset, 375 | .read = ram_read, 376 | .write = ram_write, 377 | }; 378 | 379 | 380 | struct hw_device *rom_create (const char *filename, unsigned int maxsize) 381 | { 382 | FILE *fp; 383 | struct hw_device *dev; 384 | unsigned int image_size; 385 | char *buf; 386 | 387 | if (filename) 388 | { 389 | fp = file_open (NULL, filename, "rb"); 390 | if (!fp) 391 | return NULL; 392 | image_size = sizeof_file (fp); 393 | } 394 | 395 | buf = malloc (maxsize); 396 | dev = device_attach (&rom_class, maxsize, buf); 397 | if (filename) 398 | { 399 | fread (buf, image_size, 1, fp); 400 | fclose (fp); 401 | maxsize -= image_size; 402 | while (maxsize > 0) 403 | { 404 | memcpy (buf + image_size, buf, image_size); 405 | buf += image_size; 406 | maxsize -= image_size; 407 | } 408 | } 409 | 410 | return dev; 411 | } 412 | 413 | /**********************************************************/ 414 | 415 | U8 console_read (struct hw_device *dev, unsigned long addr) 416 | { 417 | switch (addr) 418 | { 419 | case CON_IN: 420 | return getchar (); 421 | default: 422 | return MISSING; 423 | } 424 | } 425 | 426 | void console_write (struct hw_device *dev, unsigned long addr, U8 val) 427 | { 428 | switch (addr) 429 | { 430 | case CON_OUT: 431 | putchar (val); 432 | break; 433 | case CON_EXIT: 434 | sim_exit (val); 435 | break; 436 | default: 437 | break; 438 | } 439 | } 440 | 441 | struct hw_class console_class = 442 | { 443 | .readonly = 0, 444 | .reset = null_reset, 445 | .read = console_read, 446 | .write = console_write, 447 | }; 448 | 449 | struct hw_device *console_create (void) 450 | { 451 | return device_attach (&console_class, BUS_MAP_SIZE, NULL); 452 | } 453 | 454 | /**********************************************************/ 455 | 456 | 457 | U8 mmu_regs[MMU_PAGECOUNT][MMU_PAGEREGS]; 458 | 459 | U8 mmu_read (struct hw_device *dev, unsigned long addr) 460 | { 461 | switch (addr) 462 | { 463 | case 0x60: 464 | return fault_addr >> 8; 465 | case 0x61: 466 | return fault_addr & 0xFF; 467 | case 0x62: 468 | return fault_type; 469 | default: 470 | { 471 | unsigned int page = (addr / MMU_PAGEREGS) % MMU_PAGECOUNT; 472 | unsigned int reg = addr % MMU_PAGEREGS; 473 | U8 val = mmu_regs[page][reg]; 474 | //printf ("\n%02X, %02X = %02X\n", page, reg, val); 475 | return val; 476 | } 477 | } 478 | } 479 | 480 | void mmu_write (struct hw_device *dev, unsigned long addr, U8 val) 481 | { 482 | unsigned int page = (addr / MMU_PAGEREGS) % MMU_PAGECOUNT; 483 | unsigned int reg = addr % MMU_PAGEREGS; 484 | mmu_regs[page][reg] = val; 485 | 486 | bus_map (page * MMU_PAGESIZE, 487 | mmu_regs[page][0], 488 | mmu_regs[page][1] * MMU_PAGESIZE, 489 | MMU_PAGESIZE, 490 | mmu_regs[page][2] & MAP_READWRITE); 491 | } 492 | 493 | void mmu_reset (struct hw_device *dev) 494 | { 495 | unsigned int page; 496 | for (page = 0; page < MMU_PAGECOUNT; page++) 497 | { 498 | mmu_write (dev, page * MMU_PAGEREGS + 0, 0); 499 | mmu_write (dev, page * MMU_PAGEREGS + 1, 0); 500 | mmu_write (dev, page * MMU_PAGEREGS + 2, MAP_READWRITE); 501 | } 502 | } 503 | 504 | void mmu_reset_complete (struct hw_device *dev) 505 | { 506 | unsigned int page; 507 | const struct bus_map *map; 508 | 509 | /* Examine all of the bus_maps in place now, and 510 | sync with the MMU registers. */ 511 | for (page = 0; page < MMU_PAGECOUNT; page++) 512 | { 513 | map = &busmaps[4 + page * (MMU_PAGESIZE / BUS_MAP_SIZE)]; 514 | mmu_regs[page][0] = map->devid; 515 | mmu_regs[page][1] = map->offset / MMU_PAGESIZE; 516 | mmu_regs[page][2] = map->flags & MAP_READWRITE; 517 | /* printf ("%02X %02X %02X\n", 518 | map->devid, map->offset / MMU_PAGESIZE, 519 | map->flags); */ 520 | } 521 | } 522 | 523 | 524 | struct hw_class mmu_class = 525 | { 526 | .readonly = 0, 527 | .reset = mmu_reset, 528 | .read = mmu_read, 529 | .write = mmu_write, 530 | }; 531 | 532 | struct hw_device *mmu_create (void) 533 | { 534 | return device_attach (&mmu_class, BUS_MAP_SIZE, NULL); 535 | } 536 | 537 | 538 | /**********************************************************/ 539 | 540 | void machine_update (void) 541 | { 542 | int i; 543 | for (i=0; i < device_count; i++) 544 | { 545 | struct hw_device *dev = device_table[i]; 546 | if (dev->class_ptr->update) 547 | dev->class_ptr->update (dev); 548 | } 549 | } 550 | 551 | int machine_match (const char *machine_name, const char *boot_rom_file, struct machine *m) 552 | { 553 | if (!strcmp (m->name, machine_name)) 554 | { 555 | machine = m; 556 | m->init (boot_rom_file); 557 | return 1; 558 | } 559 | return 0; 560 | } 561 | 562 | 563 | void machine_init (const char *machine_name, const char *boot_rom_file) 564 | { 565 | extern struct machine simple_machine; 566 | extern struct machine eon_machine; 567 | extern struct machine eon2_machine; 568 | extern struct machine wpc_machine; 569 | int i; 570 | 571 | /* Initialize CPU maps, so that no CPU addresses map to 572 | anything. Default maps will trigger faults at runtime. */ 573 | null_device = null_create (); 574 | memset (busmaps, 0, sizeof (busmaps)); 575 | for (i = 0; i < NUM_BUS_MAPS; i++) 576 | busmaps[i].devid = INVALID_DEVID; 577 | 578 | if (machine_match (machine_name, boot_rom_file, &simple_machine)); 579 | else if (machine_match (machine_name, boot_rom_file, &eon_machine)); 580 | else if (machine_match (machine_name, boot_rom_file, &eon2_machine)); 581 | else if (machine_match (machine_name, boot_rom_file, &wpc_machine)); 582 | else exit (1); 583 | 584 | /* Save the default busmap configuration, before the 585 | CPU begins to run, so that it can be restored if 586 | necessary. */ 587 | memcpy (default_busmaps, busmaps, sizeof (busmaps)); 588 | 589 | if (!strcmp (machine_name, "eon")) 590 | mmu_reset_complete (mmu_device); 591 | } 592 | 593 | -------------------------------------------------------------------------------- /machine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2006-2009 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef M6809_MACHINE_H 22 | #define M6809_MACHINE_H 23 | 24 | /* This file defines structures used to build generic machines on a 6809. */ 25 | 26 | typedef unsigned char U8; 27 | typedef unsigned short U16; 28 | 29 | typedef unsigned long absolute_address_t; 30 | 31 | #define MAX_CPU_ADDR 65536 32 | 33 | /* The generic bus architecture. */ 34 | 35 | /* Up to 32 devices may be connected. Each device is addressed by a 32-bit physical address */ 36 | #define MAX_BUS_DEVICES 32 37 | 38 | #define INVALID_DEVID 0xff 39 | 40 | /* Say whether or not the mapping is RO or RW (or neither). */ 41 | #define MAP_READABLE 0x1 42 | #define MAP_WRITABLE 0x2 43 | #define MAP_READWRITE 0x3 44 | 45 | /* A fixed map cannot be reprogrammed. Attempts to 46 | bus_map something differently will silently be 47 | ignored. */ 48 | #define MAP_FIXED 0x4 49 | 50 | #define FAULT_NONE 0 51 | #define FAULT_NOT_WRITABLE 1 52 | #define FAULT_NO_RESPONSE 2 53 | #define FAULT_NOT_READABLE 3 54 | 55 | /* A bus map is assocated with part of the 6809 address space 56 | and says what device and which part of it is mapped into that 57 | area. It also has associated flags which say how it is allowed 58 | to be accessed. 59 | 60 | A single bus map defines 128 bytes of address space; for a 64KB CPU, 61 | that requires a total of 512 such structures. 62 | 63 | Note that the bus map need not correspond to the page size that can 64 | be configured by the MMU. It allows for more granularity and is 65 | needed in some *hardcoded* mapping cases. */ 66 | 67 | #define BUS_MAP_SIZE 128 68 | 69 | struct bus_map 70 | { 71 | unsigned int devid; /* The devid mapped here */ 72 | unsigned long offset; /* The offset within the device */ 73 | unsigned char flags; 74 | }; 75 | 76 | #define NUM_BUS_MAPS (MAX_CPU_ADDR / BUS_MAP_SIZE) 77 | 78 | 79 | /* A hardware device structure exists for each physical device 80 | in the machine */ 81 | 82 | struct hw_device; 83 | 84 | /* A hardware class structure exists for each type of device. 85 | It defines the operations that are allowed on that device. 86 | For example, if there are multiple ROM chips, then there is 87 | a single "ROM" class and multiple ROM device objects. */ 88 | 89 | struct hw_class 90 | { 91 | /* Nonzero if the device is readonly */ 92 | int readonly; 93 | 94 | /* Resets the device */ 95 | void (*reset) (struct hw_device *dev); 96 | 97 | /* Reads a byte at a given offset from the beginning of the device. */ 98 | U8 (*read) (struct hw_device *dev, unsigned long phy_addr); 99 | 100 | /* Writes a byte at a given offset from the beginning of the device. */ 101 | void (*write) (struct hw_device *dev, unsigned long phy_addr, U8 val); 102 | 103 | /* Update procedure. This is called periodically and can be used for 104 | whatever purpose. The minimum update interval is once per 1ms. Leave 105 | NULL if not required */ 106 | void (*update) (struct hw_device *dev); 107 | }; 108 | 109 | 110 | /* The hardware device structure exists for each instance of a device. */ 111 | 112 | struct hw_device 113 | { 114 | /* A pointer to the class object. This says what kind of device it is. */ 115 | struct hw_class *class_ptr; 116 | 117 | /* The device ID assigned to it. This is filled in automatically 118 | by the simulator. */ 119 | unsigned int devid; 120 | 121 | /* The total size of the device in bytes. */ 122 | unsigned long size; 123 | 124 | /* The private pointer, which is interpreted differently for each type 125 | (hw_class) of device. */ 126 | void *priv; 127 | }; 128 | 129 | /* The machine structure collects everything about the abstract machine. 130 | The pointer 'machine' points to the machine that is being run. */ 131 | 132 | extern struct machine *machine; 133 | 134 | struct machine 135 | { 136 | const char *name; 137 | void (*init) (const char *boot_rom_file); 138 | void (*fault) (unsigned int addr, unsigned char type); 139 | void (*dump_thread) (unsigned int thread_id); 140 | void (*periodic) (void); 141 | unsigned long cycles_per_sec; 142 | }; 143 | 144 | struct hw_device *device_attach (struct hw_class *class_ptr, unsigned int size, void *priv); 145 | 146 | struct hw_device *ram_create (unsigned long size); 147 | struct hw_device *rom_create (const char *filename, unsigned int maxsize); 148 | struct hw_device *console_create (void); 149 | struct hw_device *disk_create (const char *backing_file, struct hw_device *ram_dev); 150 | 151 | #endif /* _M6809_MACHINE_H */ 152 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2001 by Arto Salmi and Joze Fabcic 3 | * Copyright 2006-2008 by Brian Dominy 4 | * 5 | * This file is part of GCC6809. 6 | * 7 | * GCC6809 is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * GCC6809 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GCC6809; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | 23 | #include 24 | #include "6809.h" 25 | 26 | enum 27 | { HEX, S19, BIN }; 28 | 29 | 30 | /* The total number of cycles that have executed */ 31 | unsigned long total = 0; 32 | 33 | /* The frequency of the emulated CPU, in megahertz */ 34 | unsigned int mhz = 1; 35 | 36 | /* When nonzero, indicates that the IRQ should be triggered periodically, 37 | every so many cycles. By default no periodic IRQ is generated. */ 38 | unsigned int cycles_per_irq = 0; 39 | 40 | /* When nonzero, indicates that the FIRQ should be triggered periodically, 41 | every so many cycles. By default no periodic FIRQ is generated. */ 42 | unsigned int cycles_per_firq = 0; 43 | 44 | /* Nonzero if debugging support is turned on */ 45 | int debug_enabled = 0; 46 | 47 | /* Nonzero if tracing is enabled */ 48 | int trace_enabled = 0; 49 | 50 | /* When nonzero, causes the program to print the total number of cycles 51 | on a successful exit. */ 52 | int dump_cycles_on_success = 0; 53 | 54 | /* When nonzero, indicates the total number of cycles before an automated 55 | exit. This is to help speed through test cases that never finish. */ 56 | unsigned long max_cycles = 500000000UL; 57 | 58 | /* When nonzero, says that the state of the machine is persistent 59 | across runs of the simulator. */ 60 | int machine_persistent = 0; 61 | 62 | /* When nonzero, says that the simulator is slowed down to match what a real 63 | processor would run like. */ 64 | int machine_realtime = 0; 65 | 66 | static int type = S19; 67 | 68 | char *exename; 69 | 70 | const char *machine_name = "simple"; 71 | 72 | const char *prog_name = NULL; 73 | 74 | FILE *stat_file = NULL; 75 | 76 | struct timeval time_started; 77 | 78 | 79 | /** 80 | * Return elapsed real time in milliseconds. 81 | */ 82 | long 83 | time_diff (struct timeval *old, struct timeval *new) 84 | { 85 | long ms = (new->tv_usec - old->tv_usec) / 1000; 86 | ms += (new->tv_sec - old->tv_sec) * 1000; 87 | return ms; 88 | } 89 | 90 | 91 | long 92 | get_elapsed_realtime (void) 93 | { 94 | struct timeval now; 95 | gettimeofday (&now, NULL); 96 | return time_diff (&time_started, &now); 97 | } 98 | 99 | 100 | /* 101 | * Check if the CPU should idle. 102 | */ 103 | void 104 | idle_loop (void) 105 | { 106 | struct timeval now; 107 | static struct timeval last = { 0, 0 }; 108 | int real_ms; 109 | static unsigned long last_cycles = 0; 110 | unsigned long cycles; 111 | int sim_ms; 112 | const int cycles_per_ms = 2000; 113 | static int period = 30; 114 | static int count = 30; 115 | int delay; 116 | static int total_ms_elapsed = 0; 117 | static int cumulative_delay = 0; 118 | 119 | if (--count > 0) 120 | return; 121 | 122 | if (last.tv_sec == 0 && last.tv_usec == 0) 123 | gettimeofday (&last, NULL); 124 | 125 | gettimeofday (&now, NULL); 126 | real_ms = time_diff (&last, &now); 127 | last = now; 128 | 129 | cycles = get_cycles (); 130 | sim_ms = (cycles - last_cycles) / cycles_per_ms; 131 | if (sim_ms < 0) 132 | sim_ms += cycles_per_ms; 133 | last_cycles = cycles; 134 | 135 | total_ms_elapsed += sim_ms; 136 | if (total_ms_elapsed > 100) 137 | { 138 | total_ms_elapsed -= 100; 139 | if (machine->periodic) 140 | machine->periodic (); 141 | command_periodic (); 142 | } 143 | 144 | delay = sim_ms - real_ms; 145 | cumulative_delay += delay; 146 | if (cumulative_delay > 0) 147 | { 148 | usleep (50 * 1000UL); 149 | cumulative_delay -= 50; 150 | } 151 | 152 | count = period; 153 | } 154 | 155 | 156 | int do_help (const char *arg __attribute__((unused))); 157 | 158 | #define NO_NEG 0 159 | #define HAS_NEG 1 160 | 161 | #define NO_ARG 0 162 | #define HAS_ARG 1 163 | 164 | 165 | struct option 166 | { 167 | char o_short; 168 | const char *o_long; 169 | const char *help; 170 | unsigned int can_negate : 1; 171 | unsigned int takes_arg : 1; 172 | int *int_value; 173 | int default_value; 174 | const char **string_value; 175 | int (*handler) (const char *arg); 176 | } option_table[] = { 177 | { 'd', "debug", "Enter the monitor immediately", 178 | HAS_NEG, NO_ARG, &debug_enabled, 1, NULL, NULL }, 179 | { 'h', "help", NULL, 180 | NO_NEG, NO_ARG, NULL, 0, 0, do_help }, 181 | { 'b', "binary", "", 182 | NO_NEG, NO_ARG, &type, BIN, NULL, NULL }, 183 | { 'M', "mhz", "", NO_NEG, HAS_ARG }, 184 | { '-', "68a09", "Emulate the 68A09 variation (1.5Mhz)" }, 185 | { '-', "68b09", "Emulate the 68B09 variation (2Mhz)" }, 186 | { 'R', "realtime", "Limit simulation speed to match realtime", 187 | HAS_NEG, NO_ARG, &machine_realtime, 0, NULL, NULL }, 188 | { 'I', "irqfreq", "Asserts an IRQ every so many cycles automatically", 189 | NO_NEG, HAS_ARG, &cycles_per_irq, 0, NULL, NULL }, 190 | { 'F', "firqfreq", "Asserts an FIRQ every so many cycles automatically", 191 | NO_NEG, HAS_ARG, &cycles_per_firq, 0, NULL, NULL }, 192 | { 'C', "cycledump", "", 193 | HAS_NEG, NO_ARG, &dump_cycles_on_success, 1, NULL, NULL}, 194 | { 't', "loadmap", "" }, 195 | { 'T', "trace", "", 196 | NO_NEG, NO_ARG, &trace_enabled, 1, NULL, NULL }, 197 | { 'm', "maxcycles", "Sets maximum number of cycles to run", 198 | NO_NEG, HAS_ARG, &max_cycles, 0, NULL, NULL }, 199 | { 's', "machine", "Specify the machine (exact hardware) to emulate", 200 | NO_NEG, HAS_ARG, NULL, 0, &machine_name, NULL }, 201 | { 'p', "persistent", "Use persistent machine state", 202 | NO_NEG, NO_ARG, &machine_persistent, 1, NULL, NULL }, 203 | { '\0', NULL }, 204 | }; 205 | 206 | 207 | int 208 | do_help (const char *arg __attribute__((unused))) 209 | { 210 | struct option *opt = option_table; 211 | 212 | printf ("Motorola 6809 Simulator Version %s\n", PACKAGE_VERSION); 213 | printf ("m6809-run [options] [program]\n\n"); 214 | printf ("Options:\n"); 215 | while (opt->o_long != NULL) 216 | { 217 | if (opt->help) 218 | { 219 | if (opt->o_short == '-') 220 | printf (" --%-16.16s %s\n", opt->o_long, opt->help); 221 | else 222 | printf (" -%c, --%-16.16s%s\n", opt->o_short, opt->o_long, opt->help); 223 | } 224 | opt++; 225 | } 226 | exit (0); 227 | } 228 | 229 | 230 | void usage (void) 231 | { 232 | do_help (NULL); 233 | } 234 | 235 | 236 | /** 237 | * Returns positive if an argument was taken. 238 | * Returns zero if no argument was taken. 239 | * Returns negative on error. 240 | */ 241 | int 242 | process_option (struct option *opt, const char *arg) 243 | { 244 | int rc; 245 | //printf ("Processing option '%s'\n", opt->o_long); 246 | if (opt->takes_arg) 247 | { 248 | if (!arg) 249 | { 250 | //printf (" Takes argument but none given.\n"); 251 | rc = 0; 252 | } 253 | else 254 | { 255 | if (opt->int_value) 256 | { 257 | *(opt->int_value) = strtoul (arg, NULL, 0); 258 | //printf (" Integer argument '%d' taken.\n", *(opt->int_value)); 259 | } 260 | else if (opt->string_value) 261 | { 262 | *(opt->string_value) = arg; 263 | //printf (" String argument '%s' taken.\n", *(opt->string_value)); 264 | } 265 | rc = 1; 266 | } 267 | } 268 | else 269 | { 270 | if (arg) 271 | //printf (" Takes no argument but one given, ignored.\n"); 272 | 273 | if (opt->int_value) 274 | { 275 | *(opt->int_value) = opt->default_value; 276 | //printf (" Integer argument 1 implied.\n"); 277 | } 278 | rc = 0; 279 | } 280 | 281 | if (opt->handler) 282 | { 283 | rc = opt->handler (arg); 284 | //printf (" Handler called, rc=%d\n", rc); 285 | } 286 | 287 | if (rc < 0) 288 | sim_exit (0x70); 289 | return rc; 290 | } 291 | 292 | 293 | int 294 | process_plain_argument (const char *arg) 295 | { 296 | //printf ("plain argument '%s'\n", arg); 297 | if (!prog_name) 298 | prog_name = arg; 299 | } 300 | 301 | 302 | int 303 | parse_args (int argc, char *argv[]) 304 | { 305 | int argn = 1; 306 | struct option *opt; 307 | 308 | next_arg: 309 | while (argn < argc) 310 | { 311 | char *arg = argv[argn]; 312 | if (arg[0] == '-') 313 | { 314 | if (arg[1] == '-') 315 | { 316 | char *rest = strchr (arg+2, '='); 317 | if (rest) 318 | *rest++ = '\0'; 319 | 320 | opt = option_table; 321 | while (opt->o_long != NULL) 322 | { 323 | if (!strcmp (opt->o_long, arg+2)) 324 | { 325 | argn++; 326 | (void)process_option (opt, rest); 327 | goto next_arg; 328 | } 329 | opt++; 330 | } 331 | printf ("long option '%s' not recognized.\n", arg+2); 332 | } 333 | else 334 | { 335 | opt = option_table; 336 | while (opt->o_long != NULL) 337 | { 338 | if (opt->o_short == arg[1]) 339 | { 340 | argn++; 341 | if (process_option (opt, argv[argn])) 342 | argn++; 343 | goto next_arg; 344 | } 345 | opt++; 346 | } 347 | printf ("short option '%c' not recognized.\n", arg[1]); 348 | } 349 | argn++; 350 | } 351 | else 352 | { 353 | process_plain_argument (argv[argn++]); 354 | } 355 | } 356 | } 357 | 358 | 359 | 360 | int 361 | main (int argc, char *argv[]) 362 | { 363 | int off = 0; 364 | int i, j, n; 365 | int argn = 1; 366 | unsigned int loops = 0; 367 | 368 | gettimeofday (&time_started, NULL); 369 | 370 | exename = argv[0]; 371 | /* TODO - enable different options by default 372 | based on the executable name. */ 373 | 374 | parse_args (argc, argv); 375 | 376 | sym_init (); 377 | 378 | switch (type) 379 | { 380 | case HEX: 381 | if (prog_name && load_hex (prog_name)) 382 | usage (); 383 | break; 384 | 385 | case S19: 386 | /* The machine loader cannot deal with S-record files. 387 | So initialize the machine first, passing it a NULL 388 | filename, then load the S-record file afterwards. */ 389 | machine_init (machine_name, NULL); 390 | if (prog_name && load_s19 (prog_name)) 391 | usage (); 392 | break; 393 | 394 | default: 395 | machine_init (machine_name, prog_name); 396 | break; 397 | } 398 | 399 | /* Try to load a map file */ 400 | if (prog_name) 401 | load_map_file (prog_name); 402 | 403 | /* Enable debugging if no executable given yet. */ 404 | if (!prog_name) 405 | debug_enabled = 1; 406 | else 407 | /* OK, ready to run. Reset the CPU first. */ 408 | cpu_reset (); 409 | 410 | monitor_init (); 411 | command_init (); 412 | keybuffering (0); 413 | 414 | /* Now, iterate through the instructions. 415 | * If no IRQs or FIRQs are enabled, we can just call cpu_execute() 416 | * and let it run for a long time; otherwise, we need to come back 417 | * here periodically and do the interrupt handling. */ 418 | for (cpu_quit = 1; cpu_quit != 0;) 419 | { 420 | if ((cycles_per_irq == 0) && (cycles_per_firq == 0)) 421 | { 422 | /* Simulate some CPU time, either 1ms worth or up to the 423 | next possible IRQ */ 424 | total += cpu_execute (mhz * 1024); 425 | 426 | /* Call each device that needs periodic processing. */ 427 | machine_update (); 428 | } 429 | else 430 | { 431 | total += cpu_execute (cycles_per_irq); 432 | /* TODO - this assumes periodic interrupts (WPC) */ 433 | request_irq (0); 434 | { 435 | /* TODO - FIRQ frequency not handled yet */ 436 | static int firq_freq = 0; 437 | if (++firq_freq == 8) 438 | { 439 | request_firq (0); 440 | firq_freq = 0; 441 | } 442 | } 443 | } 444 | 445 | idle_loop (); 446 | 447 | /* Check for a rogue program that won't end */ 448 | if ((max_cycles > 0) && (total > max_cycles)) 449 | { 450 | sim_error ("maximum cycle count exceeded at %s\n", 451 | monitor_addr_name (get_pc ())); 452 | } 453 | } 454 | 455 | sim_exit (0); 456 | return 0; 457 | } 458 | -------------------------------------------------------------------------------- /mmu.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "machine.h" 4 | 5 | #define SMR_PAGESIZE 4096 6 | 7 | #define SMR_SLOTS 16 8 | 9 | /* Small MMU register map */ 10 | #define SMR_SLOT 0 /* Which slot is described by registers 8-9 */ 11 | #define SMR_BASEL 1 /* The base page for lower 8 slots */ 12 | #define SMR_BASEH 2 /* The base page for upper 8 slots */ 13 | #define SMR_FAULTA 3 /* The faulting address */ 14 | #define SMR_FAULTT 5 /* The fault type */ 15 | #define SM_GLOBAL_REGS 6 16 | #define SMR_PAGE 6 /* Which 4KB page is mapped to the current slot */ 17 | #define SMR_FLAGS 7 /* What are the page flags for this slot */ 18 | 19 | /* The 'small' MMU is an I/O device that allows remapping a window of 20 | a single device into a fixed region of the CPU. */ 21 | struct small_mmu 22 | { 23 | struct hw_device *realdev; 24 | unsigned int page_size; 25 | U8 global_regs[8]; 26 | U8 slot_regs[SMR_SLOTS][2]; 27 | }; 28 | 29 | void small_mmu_update_slot (struct small_mmu *mmu, unsigned int slot) 30 | { 31 | unsigned int page = mmu->slot_regs[slot][SMR_PAGE - SM_GLOBAL_REGS]; 32 | unsigned int flags = mmu->slot_regs[slot][SMR_FLAGS - SM_GLOBAL_REGS]; 33 | bus_map (slot * SMR_PAGESIZE, mmu->realdev->devid, page, SMR_PAGESIZE, 34 | flags & MAP_READWRITE); 35 | } 36 | 37 | void small_mmu_update_current (struct small_mmu *mmu) 38 | { 39 | small_mmu_update_slot (mmu, mmu->global_regs[0]); 40 | } 41 | 42 | void small_mmu_update_all (struct small_mmu *mmu) 43 | { 44 | unsigned int slot; 45 | for (slot = 0; slot < SMR_SLOTS; slot++) 46 | small_mmu_update_slot (mmu, slot); 47 | } 48 | 49 | U8 small_mmu_read (struct hw_device *dev, unsigned long addr) 50 | { 51 | struct small_mmu *mmu = (struct small_mmu *)dev->priv; 52 | if (addr < SM_GLOBAL_REGS) 53 | return mmu->global_regs[addr]; 54 | else 55 | return mmu->slot_regs[mmu->global_regs[0]][addr - SM_GLOBAL_REGS]; 56 | } 57 | 58 | void small_mmu_write (struct hw_device *dev, unsigned long addr, U8 val) 59 | { 60 | struct small_mmu *mmu = (struct small_mmu *)dev->priv; 61 | 62 | if (addr < SM_GLOBAL_REGS) 63 | mmu->global_regs[addr] = val; 64 | else 65 | mmu->slot_regs[mmu->global_regs[0]][addr - SM_GLOBAL_REGS] = val; 66 | 67 | switch (addr) 68 | { 69 | case SMR_PAGE: 70 | case SMR_FLAGS: 71 | { 72 | unsigned int slot = mmu->global_regs[0]; 73 | unsigned int page = mmu->slot_regs[slot][SMR_PAGE - SM_GLOBAL_REGS]; 74 | unsigned int flags = mmu->slot_regs[slot][SMR_FLAGS - SM_GLOBAL_REGS]; 75 | bus_map (slot * SMR_PAGESIZE, mmu->realdev->devid, page * SMR_PAGESIZE, 76 | SMR_PAGESIZE, flags & MAP_READWRITE); 77 | break; 78 | } 79 | } 80 | } 81 | 82 | void small_mmu_reset (struct hw_device *dev) 83 | { 84 | unsigned int page; 85 | struct small_mmu *mmu = (struct small_mmu *)dev->priv; 86 | 87 | for (page = 0; page < SMR_SLOTS; page++) 88 | { 89 | small_mmu_write (dev, SMR_SLOT, page); 90 | small_mmu_write (dev, SMR_PAGE, page); 91 | small_mmu_write (dev, SMR_FLAGS, MAP_READWRITE); 92 | } 93 | } 94 | 95 | struct hw_class small_mmu_class = 96 | { 97 | .readonly = 0, 98 | .reset = small_mmu_reset, 99 | .read = small_mmu_read, 100 | .write = small_mmu_write, 101 | }; 102 | 103 | struct hw_device *small_mmu_create (struct hw_device *realdev) 104 | { 105 | struct small_mmu *mmu = malloc (sizeof (struct small_mmu)); 106 | mmu->realdev = realdev; 107 | mmu->page_size = SMR_PAGESIZE; 108 | return device_attach (&small_mmu_class, 16, mmu); /* 16 = sizeof I/O window */ 109 | } 110 | 111 | 112 | -------------------------------------------------------------------------------- /monitor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2001 by Arto Salmi and Joze Fabcic 3 | * Copyright 2006-2008 by Brian Dominy 4 | * 5 | * This file is part of GCC6809. 6 | * 7 | * GCC6809 is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * GCC6809 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GCC6809; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | 23 | #include "6809.h" 24 | #include "monitor.h" 25 | #include 26 | #include 27 | 28 | 29 | /* The function call stack */ 30 | struct function_call fctab[MAX_FUNCTION_CALLS]; 31 | 32 | /* The top of the function call stack */ 33 | struct function_call *current_function_call; 34 | 35 | /* Automatically break after executing this many instructions */ 36 | int auto_break_insn_count = 0; 37 | 38 | int monitor_on = 0; 39 | 40 | int dump_every_insn = 0; 41 | 42 | 43 | enum addr_mode 44 | { 45 | _illegal, _implied, _imm_byte, _imm_word, _direct, _extended, 46 | _indexed, _rel_byte, _rel_word, _reg_post, _sys_post, _usr_post 47 | }; 48 | 49 | enum opcode 50 | { 51 | _undoc, _abx, _adca, _adcb, _adda, _addb, _addd, _anda, _andb, 52 | _andcc, _asla, _aslb, _asl, _asra, _asrb, _asr, _bcc, _lbcc, 53 | _bcs, _lbcs, _beq, _lbeq, _bge, _lbge, _bgt, _lbgt, _bhi, 54 | _lbhi, _bita, _bitb, _ble, _lble, _bls, _lbls, _blt, _lblt, 55 | _bmi, _lbmi, _bne, _lbne, _bpl, _lbpl, _bra, _lbra, _brn, 56 | _lbrn, _bsr, _lbsr, _bvc, _lbvc, _bvs, _lbvs, _clra, _clrb, 57 | _clr, _cmpa, _cmpb, _cmpd, _cmps, _cmpu, _cmpx, _cmpy, _coma, 58 | _comb, _com, _cwai, _daa, _deca, _decb, _dec, _eora, _eorb, 59 | _exg, _inca, _incb, _inc, _jmp, _jsr, _lda, _ldb, _ldd, 60 | _lds, _ldu, _ldx, _ldy, _leas, _leau, _leax, _leay, _lsra, 61 | _lsrb, _lsr, _mul, _nega, _negb, _neg, _nop, _ora, _orb, 62 | _orcc, _pshs, _pshu, _puls, _pulu, _rola, _rolb, _rol, _rora, 63 | _rorb, _ror, _rti, _rts, _sbca, _sbcb, _sex, _sta, _stb, 64 | _std, _sts, _stu, _stx, _sty, _suba, _subb, _subd, _swi, 65 | _swi2, _swi3, _sync, _tfr, _tsta, _tstb, _tst, _reset, 66 | #ifdef H6309 67 | _negd, _comd, _lsrd, _rord, _asrd, _rold, _decd, _incd, _tstd, 68 | _clrd 69 | #endif 70 | }; 71 | 72 | char *mne[] = { 73 | "???", "ABX", "ADCA", "ADCB", "ADDA", "ADDB", "ADDD", "ANDA", "ANDB", 74 | "ANDCC", "ASLA", "ASLB", "ASL", "ASRA", "ASRB", "ASR", "BCC", "LBCC", 75 | "BCS", "LBCS", "BEQ", "LBEQ", "BGE", "LBGE", "BGT", "LBGT", "BHI", 76 | "LBHI", "BITA", "BITB", "BLE", "LBLE", "BLS", "LBLS", "BLT", "LBLT", 77 | "BMI", "LBMI", "BNE", "LBNE", "BPL", "LBPL", "BRA", "LBRA", "BRN", 78 | "LBRN", "BSR", "LBSR", "BVC", "LBVC", "BVS", "LBVS", "CLRA", "CLRB", 79 | "CLR", "CMPA", "CMPB", "CMPD", "CMPS", "CMPU", "CMPX", "CMPY", "COMA", 80 | "COMB", "COM", "CWAI", "DAA", "DECA", "DECB", "DEC", "EORA", "EORB", 81 | "EXG", "INCA", "INCB", "INC", "JMP", "JSR", "LDA", "LDB", "LDD", 82 | "LDS", "LDU", "LDX", "LDY", "LEAS", "LEAU", "LEAX", "LEAY", "LSRA", 83 | "LSRB", "LSR", "MUL", "NEGA", "NEGB", "NEG", "NOP", "ORA", "ORB", 84 | "ORCC", "PSHS", "PSHU", "PULS", "PULU", "ROLA", "ROLB", "ROL", "RORA", 85 | "RORB", "ROR", "RTI", "RTS", "SBCA", "SBCB", "SEX", "STA", "STB", 86 | "STD", "STS", "STU", "STX", "STY", "SUBA", "SUBB", "SUBD", "SWI", 87 | "SWI2", "SWI3", "SYNC", "TFR", "TSTA", "TSTB", "TST", "RESET", 88 | #ifdef H6309 89 | "NEGD", "COMD", "LSRD", "RORD", "ASRD", "ROLD", "DECD", 90 | "INCD", "TSTD", "CLRD", 91 | #endif 92 | }; 93 | 94 | typedef struct 95 | { 96 | UINT8 code; 97 | UINT8 mode; 98 | } opcode_t; 99 | 100 | opcode_t codes[256] = { 101 | {_neg, _direct}, 102 | {_undoc, _illegal}, 103 | {_undoc, _illegal}, 104 | {_com, _direct}, 105 | {_lsr, _direct}, 106 | {_undoc, _illegal}, 107 | {_ror, _direct}, 108 | {_asr, _direct}, 109 | {_asl, _direct}, 110 | {_rol, _direct}, 111 | {_dec, _direct}, 112 | {_undoc, _illegal}, 113 | {_inc, _direct}, 114 | {_tst, _direct}, 115 | {_jmp, _direct}, 116 | {_clr, _direct}, 117 | {_undoc, _illegal}, 118 | {_undoc, _illegal}, 119 | {_nop, _implied}, 120 | {_sync, _implied}, 121 | {_undoc, _illegal}, 122 | {_undoc, _illegal}, 123 | {_lbra, _rel_word}, 124 | {_lbsr, _rel_word}, 125 | {_undoc, _illegal}, 126 | {_daa, _implied}, 127 | {_orcc, _imm_byte}, 128 | {_undoc, _illegal}, 129 | {_andcc, _imm_byte}, 130 | {_sex, _implied}, 131 | {_exg, _reg_post}, 132 | {_tfr, _reg_post}, 133 | {_bra, _rel_byte}, 134 | {_brn, _rel_byte}, 135 | {_bhi, _rel_byte}, 136 | {_bls, _rel_byte}, 137 | {_bcc, _rel_byte}, 138 | {_bcs, _rel_byte}, 139 | {_bne, _rel_byte}, 140 | {_beq, _rel_byte}, 141 | {_bvc, _rel_byte}, 142 | {_bvs, _rel_byte}, 143 | {_bpl, _rel_byte}, 144 | {_bmi, _rel_byte}, 145 | {_bge, _rel_byte}, 146 | {_blt, _rel_byte}, 147 | {_bgt, _rel_byte}, 148 | {_ble, _rel_byte}, 149 | {_leax, _indexed}, 150 | {_leay, _indexed}, 151 | {_leas, _indexed}, 152 | {_leau, _indexed}, 153 | {_pshs, _sys_post}, 154 | {_puls, _sys_post}, 155 | {_pshu, _usr_post}, 156 | {_pulu, _usr_post}, 157 | {_undoc, _illegal}, 158 | {_rts, _implied}, 159 | {_abx, _implied}, 160 | {_rti, _implied}, 161 | {_cwai, _imm_byte}, 162 | {_mul, _implied}, 163 | {_reset, _implied}, 164 | {_swi, _implied}, 165 | {_nega, _implied}, 166 | {_undoc, _illegal}, 167 | {_undoc, _illegal}, 168 | {_coma, _implied}, 169 | {_lsra, _implied}, 170 | {_undoc, _illegal}, 171 | {_rora, _implied}, 172 | {_asra, _implied}, 173 | {_asla, _implied}, 174 | {_rola, _implied}, 175 | {_deca, _implied}, 176 | {_undoc, _illegal}, 177 | {_inca, _implied}, 178 | {_tsta, _implied}, 179 | {_undoc, _illegal}, 180 | {_clra, _implied}, 181 | {_negb, _implied}, 182 | {_undoc, _illegal}, 183 | {_undoc, _illegal}, 184 | {_comb, _implied}, 185 | {_lsrb, _implied}, 186 | {_undoc, _illegal}, 187 | {_rorb, _implied}, 188 | {_asrb, _implied}, 189 | {_aslb, _implied}, 190 | {_rolb, _implied}, 191 | {_decb, _implied}, 192 | {_undoc, _illegal}, 193 | {_incb, _implied}, 194 | {_tstb, _implied}, 195 | {_undoc, _illegal}, 196 | {_clrb, _implied}, 197 | {_neg, _indexed}, 198 | {_undoc, _illegal}, 199 | {_undoc, _illegal}, 200 | {_com, _indexed}, 201 | {_lsr, _indexed}, 202 | {_undoc, _illegal}, 203 | {_ror, _indexed}, 204 | {_asr, _indexed}, 205 | {_asl, _indexed}, 206 | {_rol, _indexed}, 207 | {_dec, _indexed}, 208 | {_undoc, _illegal}, 209 | {_inc, _indexed}, 210 | {_tst, _indexed}, 211 | {_jmp, _indexed}, 212 | {_clr, _indexed}, 213 | {_neg, _extended}, 214 | {_undoc, _illegal}, 215 | {_undoc, _illegal}, 216 | {_com, _extended}, 217 | {_lsr, _extended}, 218 | {_undoc, _illegal}, 219 | {_ror, _extended}, 220 | {_asr, _extended}, 221 | {_asl, _extended}, 222 | {_rol, _extended}, 223 | {_dec, _extended}, 224 | {_undoc, _illegal}, 225 | {_inc, _extended}, 226 | {_tst, _extended}, 227 | {_jmp, _extended}, 228 | {_clr, _extended}, 229 | {_suba, _imm_byte}, 230 | {_cmpa, _imm_byte}, 231 | {_sbca, _imm_byte}, 232 | {_subd, _imm_word}, 233 | {_anda, _imm_byte}, 234 | {_bita, _imm_byte}, 235 | {_lda, _imm_byte}, 236 | {_undoc, _illegal}, 237 | {_eora, _imm_byte}, 238 | {_adca, _imm_byte}, 239 | {_ora, _imm_byte}, 240 | {_adda, _imm_byte}, 241 | {_cmpx, _imm_word}, 242 | {_bsr, _rel_byte}, 243 | {_ldx, _imm_word}, 244 | {_undoc, _illegal}, 245 | {_suba, _direct}, 246 | {_cmpa, _direct}, 247 | {_sbca, _direct}, 248 | {_subd, _direct}, 249 | {_anda, _direct}, 250 | {_bita, _direct}, 251 | {_lda, _direct}, 252 | {_sta, _direct}, 253 | {_eora, _direct}, 254 | {_adca, _direct}, 255 | {_ora, _direct}, 256 | {_adda, _direct}, 257 | {_cmpx, _direct}, 258 | {_jsr, _direct}, 259 | {_ldx, _direct}, 260 | {_stx, _direct}, 261 | {_suba, _indexed}, 262 | {_cmpa, _indexed}, 263 | {_sbca, _indexed}, 264 | {_subd, _indexed}, 265 | {_anda, _indexed}, 266 | {_bita, _indexed}, 267 | {_lda, _indexed}, 268 | {_sta, _indexed}, 269 | {_eora, _indexed}, 270 | {_adca, _indexed}, 271 | {_ora, _indexed}, 272 | {_adda, _indexed}, 273 | {_cmpx, _indexed}, 274 | {_jsr, _indexed}, 275 | {_ldx, _indexed}, 276 | {_stx, _indexed}, 277 | {_suba, _extended}, 278 | {_cmpa, _extended}, 279 | {_sbca, _extended}, 280 | {_subd, _extended}, 281 | {_anda, _extended}, 282 | {_bita, _extended}, 283 | {_lda, _extended}, 284 | {_sta, _extended}, 285 | {_eora, _extended}, 286 | {_adca, _extended}, 287 | {_ora, _extended}, 288 | {_adda, _extended}, 289 | {_cmpx, _extended}, 290 | {_jsr, _extended}, 291 | {_ldx, _extended}, 292 | {_stx, _extended}, 293 | {_subb, _imm_byte}, 294 | {_cmpb, _imm_byte}, 295 | {_sbcb, _imm_byte}, 296 | {_addd, _imm_word}, 297 | {_andb, _imm_byte}, 298 | {_bitb, _imm_byte}, 299 | {_ldb, _imm_byte}, 300 | {_undoc, _illegal}, 301 | {_eorb, _imm_byte}, 302 | {_adcb, _imm_byte}, 303 | {_orb, _imm_byte}, 304 | {_addb, _imm_byte}, 305 | {_ldd, _imm_word}, 306 | {_undoc, _illegal}, 307 | {_ldu, _imm_word}, 308 | {_undoc, _illegal}, 309 | {_subb, _direct}, 310 | {_cmpb, _direct}, 311 | {_sbcb, _direct}, 312 | {_addd, _direct}, 313 | {_andb, _direct}, 314 | {_bitb, _direct}, 315 | {_ldb, _direct}, 316 | {_stb, _direct}, 317 | {_eorb, _direct}, 318 | {_adcb, _direct}, 319 | {_orb, _direct}, 320 | {_addb, _direct}, 321 | {_ldd, _direct}, 322 | {_std, _direct}, 323 | {_ldu, _direct}, 324 | {_stu, _direct}, 325 | {_subb, _indexed}, 326 | {_cmpb, _indexed}, 327 | {_sbcb, _indexed}, 328 | {_addd, _indexed}, 329 | {_andb, _indexed}, 330 | {_bitb, _indexed}, 331 | {_ldb, _indexed}, 332 | {_stb, _indexed}, 333 | {_eorb, _indexed}, 334 | {_adcb, _indexed}, 335 | {_orb, _indexed}, 336 | {_addb, _indexed}, 337 | {_ldd, _indexed}, 338 | {_std, _indexed}, 339 | {_ldu, _indexed}, 340 | {_stu, _indexed}, 341 | {_subb, _extended}, 342 | {_cmpb, _extended}, 343 | {_sbcb, _extended}, 344 | {_addd, _extended}, 345 | {_andb, _extended}, 346 | {_bitb, _extended}, 347 | {_ldb, _extended}, 348 | {_stb, _extended}, 349 | {_eorb, _extended}, 350 | {_adcb, _extended}, 351 | {_orb, _extended}, 352 | {_addb, _extended}, 353 | {_ldd, _extended}, 354 | {_std, _extended}, 355 | {_ldu, _extended}, 356 | {_stu, _extended} 357 | }; 358 | 359 | opcode_t codes10[256] = { 360 | {_undoc, _illegal}, 361 | {_undoc, _illegal}, 362 | {_undoc, _illegal}, 363 | {_undoc, _illegal}, 364 | {_undoc, _illegal}, 365 | {_undoc, _illegal}, 366 | {_undoc, _illegal}, 367 | {_undoc, _illegal}, 368 | {_undoc, _illegal}, 369 | {_undoc, _illegal}, 370 | {_undoc, _illegal}, 371 | {_undoc, _illegal}, 372 | {_undoc, _illegal}, 373 | {_undoc, _illegal}, 374 | {_undoc, _illegal}, 375 | {_undoc, _illegal}, 376 | {_undoc, _illegal}, 377 | {_undoc, _illegal}, 378 | {_undoc, _illegal}, 379 | {_undoc, _illegal}, 380 | {_undoc, _illegal}, 381 | {_undoc, _illegal}, 382 | {_undoc, _illegal}, 383 | {_undoc, _illegal}, 384 | {_undoc, _illegal}, 385 | {_undoc, _illegal}, 386 | {_undoc, _illegal}, 387 | {_undoc, _illegal}, 388 | {_undoc, _illegal}, 389 | {_undoc, _illegal}, 390 | {_undoc, _illegal}, 391 | {_undoc, _illegal}, 392 | {_undoc, _illegal}, 393 | {_lbrn, _rel_word}, 394 | {_lbhi, _rel_word}, 395 | {_lbls, _rel_word}, 396 | {_lbcc, _rel_word}, 397 | {_lbcs, _rel_word}, 398 | {_lbne, _rel_word}, 399 | {_lbeq, _rel_word}, 400 | {_lbvc, _rel_word}, 401 | {_lbvs, _rel_word}, 402 | {_lbpl, _rel_word}, 403 | {_lbmi, _rel_word}, 404 | {_lbge, _rel_word}, 405 | {_lblt, _rel_word}, 406 | {_lbgt, _rel_word}, 407 | {_lble, _rel_word}, 408 | {_undoc, _illegal}, 409 | {_undoc, _illegal}, 410 | {_undoc, _illegal}, 411 | {_undoc, _illegal}, 412 | {_undoc, _illegal}, 413 | {_undoc, _illegal}, 414 | {_undoc, _illegal}, 415 | {_undoc, _illegal}, 416 | {_undoc, _illegal}, 417 | {_undoc, _illegal}, 418 | {_undoc, _illegal}, 419 | {_undoc, _illegal}, 420 | {_undoc, _illegal}, 421 | {_undoc, _illegal}, 422 | {_undoc, _illegal}, 423 | {_swi2, _implied}, 424 | {_undoc, _illegal}, /* 10 40 */ 425 | {_undoc, _illegal}, 426 | {_undoc, _illegal}, 427 | {_undoc, _illegal}, 428 | {_undoc, _illegal}, 429 | {_undoc, _illegal}, 430 | {_undoc, _illegal}, 431 | {_undoc, _illegal}, 432 | {_undoc, _illegal}, 433 | {_undoc, _illegal}, 434 | {_undoc, _illegal}, 435 | {_undoc, _illegal}, 436 | {_undoc, _illegal}, 437 | {_undoc, _illegal}, 438 | {_undoc, _illegal}, 439 | {_undoc, _illegal}, 440 | {_undoc, _illegal}, 441 | {_undoc, _illegal}, 442 | {_undoc, _illegal}, 443 | {_undoc, _illegal}, 444 | {_undoc, _illegal}, 445 | {_undoc, _illegal}, 446 | {_undoc, _illegal}, 447 | {_undoc, _illegal}, 448 | {_undoc, _illegal}, 449 | {_undoc, _illegal}, 450 | {_undoc, _illegal}, 451 | {_undoc, _illegal}, 452 | {_undoc, _illegal}, 453 | {_undoc, _illegal}, 454 | {_undoc, _illegal}, 455 | {_undoc, _illegal}, 456 | {_undoc, _illegal}, 457 | {_undoc, _illegal}, 458 | {_undoc, _illegal}, 459 | {_undoc, _illegal}, 460 | {_undoc, _illegal}, 461 | {_undoc, _illegal}, 462 | {_undoc, _illegal}, 463 | {_undoc, _illegal}, 464 | {_undoc, _illegal}, 465 | {_undoc, _illegal}, 466 | {_undoc, _illegal}, 467 | {_undoc, _illegal}, 468 | {_undoc, _illegal}, 469 | {_undoc, _illegal}, 470 | {_undoc, _illegal}, 471 | {_undoc, _illegal}, 472 | {_undoc, _illegal}, 473 | {_undoc, _illegal}, 474 | {_undoc, _illegal}, 475 | {_undoc, _illegal}, 476 | {_undoc, _illegal}, 477 | {_undoc, _illegal}, 478 | {_undoc, _illegal}, 479 | {_undoc, _illegal}, 480 | {_undoc, _illegal}, 481 | {_undoc, _illegal}, 482 | {_undoc, _illegal}, 483 | {_undoc, _illegal}, 484 | {_undoc, _illegal}, 485 | {_undoc, _illegal}, 486 | {_undoc, _illegal}, 487 | {_undoc, _illegal}, 488 | {_undoc, _illegal}, 489 | {_undoc, _illegal}, 490 | {_undoc, _illegal}, 491 | {_cmpd, _imm_word}, 492 | {_undoc, _illegal}, 493 | {_undoc, _illegal}, 494 | {_undoc, _illegal}, 495 | {_undoc, _illegal}, 496 | {_undoc, _illegal}, 497 | {_undoc, _illegal}, 498 | {_undoc, _illegal}, 499 | {_undoc, _illegal}, 500 | {_cmpy, _imm_word}, 501 | {_undoc, _illegal}, 502 | {_ldy, _imm_word}, 503 | {_undoc, _illegal}, 504 | {_undoc, _illegal}, 505 | {_undoc, _illegal}, 506 | {_undoc, _illegal}, 507 | {_cmpd, _direct}, 508 | {_undoc, _illegal}, 509 | {_undoc, _illegal}, 510 | {_undoc, _illegal}, 511 | {_undoc, _illegal}, 512 | {_undoc, _illegal}, 513 | {_undoc, _illegal}, 514 | {_undoc, _illegal}, 515 | {_undoc, _illegal}, 516 | {_cmpy, _direct}, 517 | {_undoc, _illegal}, 518 | {_ldy, _direct}, 519 | {_sty, _direct}, 520 | {_undoc, _illegal}, 521 | {_undoc, _illegal}, 522 | {_undoc, _illegal}, 523 | {_cmpd, _indexed}, 524 | {_undoc, _illegal}, 525 | {_undoc, _illegal}, 526 | {_undoc, _illegal}, 527 | {_undoc, _illegal}, 528 | {_undoc, _illegal}, 529 | {_undoc, _illegal}, 530 | {_undoc, _illegal}, 531 | {_undoc, _illegal}, 532 | {_cmpy, _indexed}, 533 | {_undoc, _illegal}, 534 | {_ldy, _indexed}, 535 | {_sty, _indexed}, 536 | {_undoc, _illegal}, 537 | {_undoc, _illegal}, 538 | {_undoc, _illegal}, 539 | {_cmpd, _extended}, 540 | {_undoc, _illegal}, 541 | {_undoc, _illegal}, 542 | {_undoc, _illegal}, 543 | {_undoc, _illegal}, 544 | {_undoc, _illegal}, 545 | {_undoc, _illegal}, 546 | {_undoc, _illegal}, 547 | {_undoc, _illegal}, 548 | {_cmpy, _extended}, 549 | {_undoc, _illegal}, 550 | {_ldy, _extended}, 551 | {_sty, _extended}, 552 | {_undoc, _illegal}, 553 | {_undoc, _illegal}, 554 | {_undoc, _illegal}, 555 | {_undoc, _illegal}, 556 | {_undoc, _illegal}, 557 | {_undoc, _illegal}, 558 | {_undoc, _illegal}, 559 | {_undoc, _illegal}, 560 | {_undoc, _illegal}, 561 | {_undoc, _illegal}, 562 | {_undoc, _illegal}, 563 | {_undoc, _illegal}, 564 | {_undoc, _illegal}, 565 | {_undoc, _illegal}, 566 | {_lds, _imm_word}, 567 | {_undoc, _illegal}, 568 | {_undoc, _illegal}, 569 | {_undoc, _illegal}, 570 | {_undoc, _illegal}, 571 | {_undoc, _illegal}, 572 | {_undoc, _illegal}, 573 | {_undoc, _illegal}, 574 | {_undoc, _illegal}, 575 | {_undoc, _illegal}, 576 | {_undoc, _illegal}, 577 | {_undoc, _illegal}, 578 | {_undoc, _illegal}, 579 | {_undoc, _illegal}, 580 | {_undoc, _illegal}, 581 | {_undoc, _illegal}, 582 | {_lds, _direct}, 583 | {_sts, _direct}, 584 | {_undoc, _illegal}, 585 | {_undoc, _illegal}, 586 | {_undoc, _illegal}, 587 | {_undoc, _illegal}, 588 | {_undoc, _illegal}, 589 | {_undoc, _illegal}, 590 | {_undoc, _illegal}, 591 | {_undoc, _illegal}, 592 | {_undoc, _illegal}, 593 | {_undoc, _illegal}, 594 | {_undoc, _illegal}, 595 | {_undoc, _illegal}, 596 | {_undoc, _illegal}, 597 | {_undoc, _illegal}, 598 | {_lds, _indexed}, 599 | {_sts, _indexed}, 600 | {_undoc, _illegal}, 601 | {_undoc, _illegal}, 602 | {_undoc, _illegal}, 603 | {_undoc, _illegal}, 604 | {_undoc, _illegal}, 605 | {_undoc, _illegal}, 606 | {_undoc, _illegal}, 607 | {_undoc, _illegal}, 608 | {_undoc, _illegal}, 609 | {_undoc, _illegal}, 610 | {_undoc, _illegal}, 611 | {_undoc, _illegal}, 612 | {_undoc, _illegal}, 613 | {_undoc, _illegal}, 614 | {_lds, _extended}, 615 | {_sts, _extended} 616 | }; 617 | 618 | opcode_t codes11[256] = { 619 | {_undoc, _illegal}, 620 | {_undoc, _illegal}, 621 | {_undoc, _illegal}, 622 | {_undoc, _illegal}, 623 | {_undoc, _illegal}, 624 | {_undoc, _illegal}, 625 | {_undoc, _illegal}, 626 | {_undoc, _illegal}, 627 | {_undoc, _illegal}, 628 | {_undoc, _illegal}, 629 | {_undoc, _illegal}, 630 | {_undoc, _illegal}, 631 | {_undoc, _illegal}, 632 | {_undoc, _illegal}, 633 | {_undoc, _illegal}, 634 | {_undoc, _illegal}, 635 | {_undoc, _illegal}, 636 | {_undoc, _illegal}, 637 | {_undoc, _illegal}, 638 | {_undoc, _illegal}, 639 | {_undoc, _illegal}, 640 | {_undoc, _illegal}, 641 | {_undoc, _illegal}, 642 | {_undoc, _illegal}, 643 | {_undoc, _illegal}, 644 | {_undoc, _illegal}, 645 | {_undoc, _illegal}, 646 | {_undoc, _illegal}, 647 | {_undoc, _illegal}, 648 | {_undoc, _illegal}, 649 | {_undoc, _illegal}, 650 | {_undoc, _illegal}, 651 | {_undoc, _illegal}, 652 | {_undoc, _illegal}, 653 | {_undoc, _illegal}, 654 | {_undoc, _illegal}, 655 | {_undoc, _illegal}, 656 | {_undoc, _illegal}, 657 | {_undoc, _illegal}, 658 | {_undoc, _illegal}, 659 | {_undoc, _illegal}, 660 | {_undoc, _illegal}, 661 | {_undoc, _illegal}, 662 | {_undoc, _illegal}, 663 | {_undoc, _illegal}, 664 | {_undoc, _illegal}, 665 | {_undoc, _illegal}, 666 | {_undoc, _illegal}, 667 | {_undoc, _illegal}, 668 | {_undoc, _illegal}, 669 | {_undoc, _illegal}, 670 | {_undoc, _illegal}, 671 | {_undoc, _illegal}, 672 | {_undoc, _illegal}, 673 | {_undoc, _illegal}, 674 | {_undoc, _illegal}, 675 | {_undoc, _illegal}, 676 | {_undoc, _illegal}, 677 | {_undoc, _illegal}, 678 | {_undoc, _illegal}, 679 | {_undoc, _illegal}, 680 | {_undoc, _illegal}, 681 | {_undoc, _illegal}, 682 | {_swi3, _implied}, 683 | {_undoc, _illegal}, /* 11 40 */ 684 | {_undoc, _illegal}, 685 | {_undoc, _illegal}, 686 | {_undoc, _illegal}, 687 | {_undoc, _illegal}, 688 | {_undoc, _illegal}, 689 | {_undoc, _illegal}, 690 | {_undoc, _illegal}, 691 | {_undoc, _illegal}, 692 | {_undoc, _illegal}, 693 | {_undoc, _illegal}, 694 | {_undoc, _illegal}, 695 | {_undoc, _illegal}, 696 | {_undoc, _illegal}, 697 | {_undoc, _illegal}, 698 | {_undoc, _illegal}, 699 | {_undoc, _illegal}, 700 | {_undoc, _illegal}, 701 | {_undoc, _illegal}, 702 | {_undoc, _illegal}, 703 | {_undoc, _illegal}, 704 | {_undoc, _illegal}, 705 | {_undoc, _illegal}, 706 | {_undoc, _illegal}, 707 | {_undoc, _illegal}, 708 | {_undoc, _illegal}, 709 | {_undoc, _illegal}, 710 | {_undoc, _illegal}, 711 | {_undoc, _illegal}, 712 | {_undoc, _illegal}, 713 | {_undoc, _illegal}, 714 | {_undoc, _illegal}, 715 | {_undoc, _illegal}, 716 | {_undoc, _illegal}, 717 | {_undoc, _illegal}, 718 | {_undoc, _illegal}, 719 | {_undoc, _illegal}, 720 | {_undoc, _illegal}, 721 | {_undoc, _illegal}, 722 | {_undoc, _illegal}, 723 | {_undoc, _illegal}, 724 | {_undoc, _illegal}, 725 | {_undoc, _illegal}, 726 | {_undoc, _illegal}, 727 | {_undoc, _illegal}, 728 | {_undoc, _illegal}, 729 | {_undoc, _illegal}, 730 | {_undoc, _illegal}, 731 | {_undoc, _illegal}, 732 | {_undoc, _illegal}, 733 | {_undoc, _illegal}, 734 | {_undoc, _illegal}, 735 | {_undoc, _illegal}, 736 | {_undoc, _illegal}, 737 | {_undoc, _illegal}, 738 | {_undoc, _illegal}, 739 | {_undoc, _illegal}, 740 | {_undoc, _illegal}, 741 | {_undoc, _illegal}, 742 | {_undoc, _illegal}, 743 | {_undoc, _illegal}, 744 | {_undoc, _illegal}, 745 | {_undoc, _illegal}, 746 | {_undoc, _illegal}, 747 | {_undoc, _illegal}, 748 | {_undoc, _illegal}, 749 | {_undoc, _illegal}, 750 | {_cmpu, _imm_word}, 751 | {_undoc, _illegal}, 752 | {_undoc, _illegal}, 753 | {_undoc, _illegal}, 754 | {_undoc, _illegal}, 755 | {_undoc, _illegal}, 756 | {_undoc, _illegal}, 757 | {_undoc, _illegal}, 758 | {_undoc, _illegal}, 759 | {_cmps, _imm_word}, 760 | {_undoc, _illegal}, 761 | {_undoc, _illegal}, 762 | {_undoc, _illegal}, 763 | {_undoc, _illegal}, 764 | {_undoc, _illegal}, 765 | {_undoc, _illegal}, 766 | {_cmpu, _direct}, 767 | {_undoc, _illegal}, 768 | {_undoc, _illegal}, 769 | {_undoc, _illegal}, 770 | {_undoc, _illegal}, 771 | {_undoc, _illegal}, 772 | {_undoc, _illegal}, 773 | {_undoc, _illegal}, 774 | {_undoc, _illegal}, 775 | {_cmps, _direct}, 776 | {_undoc, _illegal}, 777 | {_undoc, _illegal}, 778 | {_undoc, _illegal}, 779 | {_undoc, _illegal}, 780 | {_undoc, _illegal}, 781 | {_undoc, _illegal}, 782 | {_cmpu, _indexed}, 783 | {_undoc, _illegal}, 784 | {_undoc, _illegal}, 785 | {_undoc, _illegal}, 786 | {_undoc, _illegal}, 787 | {_undoc, _illegal}, 788 | {_undoc, _illegal}, 789 | {_undoc, _illegal}, 790 | {_undoc, _illegal}, 791 | {_cmps, _indexed}, 792 | {_undoc, _illegal}, 793 | {_undoc, _illegal}, 794 | {_undoc, _illegal}, 795 | {_undoc, _illegal}, 796 | {_undoc, _illegal}, 797 | {_undoc, _illegal}, 798 | {_cmpu, _extended}, 799 | {_undoc, _illegal}, 800 | {_undoc, _illegal}, 801 | {_undoc, _illegal}, 802 | {_undoc, _illegal}, 803 | {_undoc, _illegal}, 804 | {_undoc, _illegal}, 805 | {_undoc, _illegal}, 806 | {_undoc, _illegal}, 807 | {_cmps, _extended}, 808 | {_undoc, _illegal}, 809 | {_undoc, _illegal}, 810 | {_undoc, _illegal}, 811 | {_undoc, _illegal}, 812 | {_undoc, _illegal}, 813 | {_undoc, _illegal}, 814 | {_undoc, _illegal}, 815 | {_undoc, _illegal}, 816 | {_undoc, _illegal}, 817 | {_undoc, _illegal}, 818 | {_undoc, _illegal}, 819 | {_undoc, _illegal}, 820 | {_undoc, _illegal}, 821 | {_undoc, _illegal}, 822 | {_undoc, _illegal}, 823 | {_undoc, _illegal}, 824 | {_undoc, _illegal}, 825 | {_undoc, _illegal}, 826 | {_undoc, _illegal}, 827 | {_undoc, _illegal}, 828 | {_undoc, _illegal}, 829 | {_undoc, _illegal}, 830 | {_undoc, _illegal}, 831 | {_undoc, _illegal}, 832 | {_undoc, _illegal}, 833 | {_undoc, _illegal}, 834 | {_undoc, _illegal}, 835 | {_undoc, _illegal}, 836 | {_undoc, _illegal}, 837 | {_undoc, _illegal}, 838 | {_undoc, _illegal}, 839 | {_undoc, _illegal}, 840 | {_undoc, _illegal}, 841 | {_undoc, _illegal}, 842 | {_undoc, _illegal}, 843 | {_undoc, _illegal}, 844 | {_undoc, _illegal}, 845 | {_undoc, _illegal}, 846 | {_undoc, _illegal}, 847 | {_undoc, _illegal}, 848 | {_undoc, _illegal}, 849 | {_undoc, _illegal}, 850 | {_undoc, _illegal}, 851 | {_undoc, _illegal}, 852 | {_undoc, _illegal}, 853 | {_undoc, _illegal}, 854 | {_undoc, _illegal}, 855 | {_undoc, _illegal}, 856 | {_undoc, _illegal}, 857 | {_undoc, _illegal}, 858 | {_undoc, _illegal}, 859 | {_undoc, _illegal}, 860 | {_undoc, _illegal}, 861 | {_undoc, _illegal}, 862 | {_undoc, _illegal}, 863 | {_undoc, _illegal}, 864 | {_undoc, _illegal}, 865 | {_undoc, _illegal}, 866 | {_undoc, _illegal}, 867 | {_undoc, _illegal}, 868 | {_undoc, _illegal}, 869 | {_undoc, _illegal}, 870 | {_undoc, _illegal}, 871 | {_undoc, _illegal}, 872 | {_undoc, _illegal}, 873 | {_undoc, _illegal}, 874 | {_undoc, _illegal} 875 | }; 876 | 877 | char *reg[] = { 878 | "D", "X", "Y", "U", "S", "PC", "??", "??", 879 | "A", "B", "CC", "DP", "??", "??", "??", "??" 880 | }; 881 | 882 | char index_reg[] = { 'X', 'Y', 'U', 'S' }; 883 | 884 | char *off4[] = { 885 | "0", "1", "2", "3", "4", "5", "6", "7", 886 | "8", "9", "10", "11", "12", "13", "14", "15", 887 | "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9", 888 | "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1" 889 | }; 890 | 891 | 892 | /* Disassemble the current instruction. Returns the number of bytes that 893 | compose it. */ 894 | int 895 | dasm (char *buf, absolute_address_t opc) 896 | { 897 | UINT8 op, am; 898 | char *op_str; 899 | absolute_address_t pc = opc; 900 | char R; 901 | int fetch1; /* the first (MSB) fetched byte, used in macro RDWORD */ 902 | 903 | op = fetch8 (); 904 | 905 | if (op == 0x10) 906 | { 907 | op = fetch8 (); 908 | am = codes10[op].mode; 909 | op = codes10[op].code; 910 | } 911 | else if (op == 0x11) 912 | { 913 | op = fetch8 (); 914 | am = codes11[op].mode; 915 | op = codes11[op].code; 916 | } 917 | else 918 | { 919 | am = codes[op].mode; 920 | op = codes[op].code; 921 | } 922 | 923 | op_str = (char *) mne[op]; 924 | buf += sprintf (buf, "%-6.6s", op_str); 925 | 926 | switch (am) 927 | { 928 | case _illegal: 929 | sprintf (buf, "???"); 930 | break; 931 | case _implied: 932 | break; 933 | case _imm_byte: 934 | sprintf (buf, "#$%02X", fetch8 ()); 935 | break; 936 | case _imm_word: 937 | sprintf (buf, "#$%04X", fetch16 ()); 938 | break; 939 | case _direct: 940 | sprintf (buf, "<%s", monitor_addr_name (fetch8 ())); 941 | break; 942 | case _extended: 943 | sprintf (buf, "%s", monitor_addr_name (fetch16 ())); 944 | break; 945 | 946 | case _indexed: 947 | op = fetch8 (); 948 | R = index_reg[(op >> 5) & 0x3]; 949 | 950 | if ((op & 0x80) == 0) 951 | { 952 | sprintf (buf, "%s,%c", off4[op & 0x1f], R); 953 | break; 954 | } 955 | 956 | switch (op & 0x1f) 957 | { 958 | case 0x00: 959 | sprintf (buf, ",%c+", R); 960 | break; 961 | case 0x01: 962 | sprintf (buf, ",%c++", R); 963 | break; 964 | case 0x02: 965 | sprintf (buf, ",-%c", R); 966 | break; 967 | case 0x03: 968 | sprintf (buf, ",--%c", R); 969 | break; 970 | case 0x04: 971 | sprintf (buf, ",%c", R); 972 | break; 973 | case 0x05: 974 | sprintf (buf, "B,%c", R); 975 | break; 976 | case 0x06: 977 | sprintf (buf, "A,%c", R); 978 | break; 979 | case 0x08: 980 | sprintf (buf, "$%02X,%c", fetch8 (), R); 981 | break; 982 | case 0x09: 983 | sprintf (buf, "$%04X,%c", fetch16 (), R); 984 | break; 985 | case 0x0B: 986 | sprintf (buf, "D,%c", R); 987 | break; 988 | case 0x0C: 989 | sprintf (buf, "$%02X,PC", fetch8 ()); 990 | break; 991 | case 0x0D: 992 | sprintf (buf, "$%04X,PC", fetch16 ()); 993 | break; 994 | case 0x11: 995 | sprintf (buf, "[,%c++]", R); 996 | break; 997 | case 0x13: 998 | sprintf (buf, "[,--%c]", R); 999 | break; 1000 | case 0x14: 1001 | sprintf (buf, "[,%c]", R); 1002 | break; 1003 | case 0x15: 1004 | sprintf (buf, "[B,%c]", R); 1005 | break; 1006 | case 0x16: 1007 | sprintf (buf, "[A,%c]", R); 1008 | break; 1009 | case 0x18: 1010 | sprintf (buf, "[$%02X,%c]", fetch8 (), R); 1011 | break; 1012 | case 0x19: 1013 | sprintf (buf, "[$%04X,%c]", fetch16 (), R); 1014 | break; 1015 | case 0x1B: 1016 | sprintf (buf, "[D,%c]", R); 1017 | break; 1018 | case 0x1C: 1019 | sprintf (buf, "[$%02X,PC]", fetch8 ()); 1020 | break; 1021 | case 0x1D: 1022 | sprintf (buf, "[$%04X,PC]", fetch16 ()); 1023 | break; 1024 | case 0x1F: 1025 | sprintf (buf, "[%s]", monitor_addr_name (fetch16 ())); 1026 | break; 1027 | default: 1028 | sprintf (buf, "???"); 1029 | break; 1030 | } 1031 | break; 1032 | 1033 | case _rel_byte: 1034 | fetch1 = ((INT8) fetch8 ()); 1035 | sprintf (buf, "%s", absolute_addr_name (fetch1 + pc)); 1036 | break; 1037 | 1038 | case _rel_word: 1039 | sprintf (buf, "%s", absolute_addr_name (fetch16 () + pc)); 1040 | break; 1041 | 1042 | case _reg_post: 1043 | op = fetch8 (); 1044 | sprintf (buf, "%s,%s", reg[op >> 4], reg[op & 15]); 1045 | break; 1046 | 1047 | case _usr_post: 1048 | case _sys_post: 1049 | op = fetch8 (); 1050 | 1051 | if (op & 0x80) 1052 | strcat (buf, "PC,"); 1053 | if (op & 0x40) 1054 | strcat (buf, am == _usr_post ? "S," : "U,"); 1055 | if (op & 0x20) 1056 | strcat (buf, "Y,"); 1057 | if (op & 0x10) 1058 | strcat (buf, "X,"); 1059 | if (op & 0x08) 1060 | strcat (buf, "DP,"); 1061 | if ((op & 0x06) == 0x06) 1062 | strcat (buf, "D,"); 1063 | else 1064 | { 1065 | if (op & 0x04) 1066 | strcat (buf, "B,"); 1067 | if (op & 0x02) 1068 | strcat (buf, "A,"); 1069 | } 1070 | if (op & 0x01) 1071 | strcat (buf, "CC,"); 1072 | buf[strlen (buf) - 1] = '\0'; 1073 | break; 1074 | 1075 | } 1076 | return pc - opc; 1077 | } 1078 | 1079 | int 1080 | sizeof_file (FILE * file) 1081 | { 1082 | int size; 1083 | 1084 | fseek (file, 0, SEEK_END); 1085 | size = ftell (file); 1086 | rewind (file); 1087 | 1088 | return size; 1089 | } 1090 | 1091 | 1092 | int 1093 | load_map_file (const char *name) 1094 | { 1095 | FILE *fp; 1096 | char map_filename[256]; 1097 | char buf[256]; 1098 | char *value_ptr, *id_ptr; 1099 | target_addr_t value; 1100 | char *file_ptr; 1101 | struct symbol *sym = NULL; 1102 | 1103 | /* Try appending the suffix 'map' to the name of the program. */ 1104 | sprintf (map_filename, "%s.map", name); 1105 | fp = file_open (NULL, map_filename, "r"); 1106 | if (!fp) 1107 | { 1108 | /* If that fails, try replacing any existing suffix. */ 1109 | sprintf (map_filename, "%s", name); 1110 | char *s = strrchr (map_filename, '.'); 1111 | if (s) 1112 | { 1113 | sprintf (s+1, "map"); 1114 | fp = file_open (NULL, map_filename, "r"); 1115 | } 1116 | 1117 | if (!fp) 1118 | { 1119 | fprintf (stderr, "warning: no symbols for %s\n", name); 1120 | return -1; 1121 | } 1122 | } 1123 | 1124 | printf ("Reading symbols from '%s'...\n", map_filename); 1125 | for (;;) 1126 | { 1127 | fgets (buf, sizeof(buf)-1, fp); 1128 | if (feof (fp)) 1129 | break; 1130 | 1131 | value_ptr = buf; 1132 | if (!strncmp (value_ptr, "page", 4)) 1133 | { 1134 | unsigned char page = strtoul (value_ptr+4, NULL, 10); 1135 | if (!strcmp (machine->name, "wpc")) 1136 | wpc_set_rom_page (page); 1137 | sym = NULL; 1138 | continue; 1139 | } 1140 | 1141 | if (strncmp (value_ptr, " ", 6)) 1142 | continue; 1143 | 1144 | while (*value_ptr == ' ') 1145 | value_ptr++; 1146 | 1147 | value = strtoul (value_ptr, &id_ptr, 16); 1148 | if (id_ptr == value_ptr) 1149 | continue; 1150 | 1151 | while (*id_ptr == ' ') 1152 | id_ptr++; 1153 | 1154 | id_ptr = strtok (id_ptr, " \t\n"); 1155 | if (((*id_ptr == 'l') || (*id_ptr == 's')) && (id_ptr[1] == '_')) 1156 | continue; 1157 | ++id_ptr; 1158 | 1159 | file_ptr = strtok (NULL, " \t\n"); 1160 | 1161 | if (sym) 1162 | sym->ty.size = to_absolute (value) - sym->value; 1163 | sym = sym_add (&program_symtab, id_ptr, to_absolute (value), 0); /* file_ptr? */ 1164 | } 1165 | 1166 | fclose (fp); 1167 | return 0; 1168 | } 1169 | 1170 | 1171 | int 1172 | load_hex (const char *name) 1173 | { 1174 | FILE *fp; 1175 | int count, addr, type, data, checksum; 1176 | int done = 1; 1177 | int line = 0; 1178 | 1179 | fp = file_open (NULL, name, "r"); 1180 | 1181 | if (fp == NULL) 1182 | { 1183 | printf ("failed to open hex record file %s.\n", name); 1184 | return 1; 1185 | } 1186 | 1187 | while (done != 0) 1188 | { 1189 | line++; 1190 | 1191 | if (fscanf (fp, ":%2x%4x%2x", &count, &addr, &type) != 3) 1192 | { 1193 | printf ("line %d: invalid hex record information.\n", line); 1194 | break; 1195 | } 1196 | 1197 | checksum = count + (addr >> 8) + (addr & 0xff) + type; 1198 | 1199 | switch (type) 1200 | { 1201 | case 0: 1202 | for (; count != 0; count--, addr++, checksum += data) 1203 | { 1204 | fscanf (fp, "%2x", &data); 1205 | write8 (addr, (UINT8) data); 1206 | } 1207 | 1208 | checksum = (-checksum) & 0xff; 1209 | fscanf (fp, "%2x", &data); 1210 | if (data != checksum) 1211 | { 1212 | printf ("line %d: invalid hex record checksum.\n", line); 1213 | done = 0; 1214 | break; 1215 | } 1216 | (void) fgetc (fp); /* skip CR/LF/NULL */ 1217 | break; 1218 | 1219 | case 1: 1220 | checksum = (-checksum) & 0xff; 1221 | fscanf (fp, "%2x", &data); 1222 | if (data != checksum) 1223 | printf ("line %d: invalid hex record checksum \n", line); 1224 | done = 0; 1225 | break; 1226 | 1227 | case 2: 1228 | default: 1229 | printf ("line %d: not supported hex type %d.\n", line, type); 1230 | done = 0; 1231 | break; 1232 | } 1233 | } 1234 | 1235 | fclose (fp); 1236 | return 0; 1237 | } 1238 | 1239 | 1240 | int 1241 | load_s19 (const char *name) 1242 | { 1243 | FILE *fp; 1244 | int count, addr, type, data, checksum; 1245 | int done = 1; 1246 | int line = 0; 1247 | 1248 | fp = file_open (NULL, name, "r"); 1249 | 1250 | if (fp == NULL) 1251 | { 1252 | printf ("failed to open S-record file %s.\n", name); 1253 | return 1; 1254 | } 1255 | 1256 | while (done != 0) 1257 | { 1258 | line++; 1259 | 1260 | if (fscanf (fp, "S%1x%2x%4x", &type, &count, &addr) != 3) 1261 | { 1262 | printf ("line %d: invalid S record information.\n", line); 1263 | break; 1264 | } 1265 | 1266 | checksum = count + (addr >> 8) + (addr & 0xff); 1267 | 1268 | switch (type) 1269 | { 1270 | case 1: 1271 | for (count -= 3; count != 0; count--, addr++, checksum += data) 1272 | { 1273 | fscanf (fp, "%2x", &data); 1274 | write8 (addr, (UINT8) data); 1275 | } 1276 | 1277 | checksum = (~checksum) & 0xff; 1278 | fscanf (fp, "%2x", &data); 1279 | if (data != checksum) 1280 | { 1281 | printf ("line %d: invalid S record checksum.\n", line); 1282 | done = 0; 1283 | break; 1284 | } 1285 | (void) fgetc (fp); /* skip CR/LF/NULL */ 1286 | break; 1287 | 1288 | case 9: 1289 | checksum = (~checksum) & 0xff; 1290 | fscanf (fp, "%2x", &data); 1291 | if (data != checksum) 1292 | printf ("line %d: invalid S record checksum.\n", line); 1293 | done = 0; 1294 | break; 1295 | 1296 | default: 1297 | printf ("line %d: S%d not supported.\n", line, type); 1298 | done = 0; 1299 | break; 1300 | } 1301 | } 1302 | 1303 | fclose (fp); 1304 | return 0; 1305 | } 1306 | 1307 | 1308 | 1309 | void 1310 | monitor_call (unsigned int flags) 1311 | { 1312 | #ifdef CALL_STACK 1313 | if (current_function_call <= &fctab[MAX_FUNCTION_CALLS-1]) 1314 | { 1315 | current_function_call++; 1316 | current_function_call->entry_point = get_pc (); 1317 | current_function_call->flags = flags; 1318 | } 1319 | #endif 1320 | #if 0 1321 | const char *id = sym_lookup (&program_symtab, to_absolute (get_pc ())); 1322 | if (id) 1323 | { 1324 | // printf ("In %s now\n", id); 1325 | } 1326 | #endif 1327 | } 1328 | 1329 | 1330 | void 1331 | monitor_return (void) 1332 | { 1333 | #ifdef CALL_STACK 1334 | if (current_function_call > &fctab[MAX_FUNCTION_CALLS-1]) 1335 | { 1336 | current_function_call--; 1337 | return; 1338 | } 1339 | 1340 | while ((current_function_call->flags & FC_TAIL_CALL) && 1341 | (current_function_call > fctab)) 1342 | { 1343 | current_function_call--; 1344 | } 1345 | 1346 | if (current_function_call > fctab) 1347 | current_function_call--; 1348 | #endif 1349 | } 1350 | 1351 | 1352 | const char * 1353 | absolute_addr_name (absolute_address_t addr) 1354 | { 1355 | static char buf[256], *bufptr; 1356 | const char *name; 1357 | 1358 | bufptr = buf; 1359 | 1360 | bufptr += sprintf (bufptr, "%02X:0x%04X", addr >> 28, addr & 0xFFFFFF); 1361 | 1362 | name = sym_lookup (&program_symtab, addr); 1363 | if (name) 1364 | bufptr += sprintf (bufptr, " <%-16.16s>", name); 1365 | 1366 | return buf; 1367 | 1368 | } 1369 | 1370 | 1371 | const char * 1372 | monitor_addr_name (target_addr_t target_addr) 1373 | { 1374 | static char buf[256], *bufptr; 1375 | const char *name; 1376 | absolute_address_t addr = to_absolute (target_addr); 1377 | 1378 | bufptr = buf; 1379 | 1380 | bufptr += sprintf (bufptr, "0x%04X", target_addr); 1381 | 1382 | name = sym_lookup (&program_symtab, addr); 1383 | if (name) 1384 | bufptr += sprintf (bufptr, " <%s>", name); 1385 | 1386 | return buf; 1387 | } 1388 | 1389 | 1390 | static void 1391 | monitor_signal (int sigtype) 1392 | { 1393 | (void) sigtype; 1394 | putchar ('\n'); 1395 | monitor_on = 1; 1396 | } 1397 | 1398 | 1399 | void 1400 | monitor_init (void) 1401 | { 1402 | int tmp; 1403 | extern int debug_enabled; 1404 | target_addr_t a; 1405 | 1406 | fctab[0].entry_point = read16 (0xfffe); 1407 | memset (&fctab[0].entry_regs, 0, sizeof (struct cpu_regs)); 1408 | current_function_call = &fctab[0]; 1409 | 1410 | auto_break_insn_count = 0; 1411 | monitor_on = debug_enabled; 1412 | signal (SIGINT, monitor_signal); 1413 | } 1414 | 1415 | 1416 | int 1417 | check_break (void) 1418 | { 1419 | if (dump_every_insn) 1420 | print_current_insn (); 1421 | 1422 | if (auto_break_insn_count > 0) 1423 | if (--auto_break_insn_count == 0) 1424 | return 1; 1425 | return 0; 1426 | } 1427 | 1428 | 1429 | void 1430 | monitor_backtrace (void) 1431 | { 1432 | struct function_call *fc = current_function_call; 1433 | while (fc >= &fctab[0]) { 1434 | printf ("%s\n", monitor_addr_name (fc->entry_point)); 1435 | fc--; 1436 | } 1437 | } 1438 | 1439 | int 1440 | monitor6809 (void) 1441 | { 1442 | int rc; 1443 | 1444 | signal (SIGINT, monitor_signal); 1445 | rc = command_loop (); 1446 | monitor_on = 0; 1447 | return rc; 1448 | } 1449 | -------------------------------------------------------------------------------- /monitor.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define S_NAMED 0x1 4 | #define S_OFFSET 0x2 5 | #define S_LINE 0x4 6 | 7 | #define MAX_BREAKPOINTS 16 8 | 9 | #define MAX_FUNCTION_CALLS 512 10 | 11 | #define BP_FREE 0x0 12 | #define BP_USED 0x1 13 | #define BP_TEMP 0x2 14 | 15 | #define PROMPT_REGS 0x1 16 | #define PROMPT_CYCLES 0x2 17 | #define PROMPT_INSN 0x4 18 | 19 | 20 | struct cpu_regs { 21 | unsigned X, Y, S, U, PC; 22 | unsigned A, B, DP; 23 | unsigned H, N, Z, OV, C; 24 | unsigned EFI; 25 | #ifdef H6309 26 | unsigned E, F, V, MD; 27 | #endif 28 | }; 29 | 30 | 31 | struct x_symbol { 32 | int flags; 33 | union { 34 | struct named_symbol { 35 | char *id; 36 | char *file; 37 | target_addr_t addr; 38 | } named; 39 | 40 | struct line_symbol { 41 | struct named_symbol *name; 42 | int lineno; 43 | } line; 44 | 45 | int offset; 46 | } u; 47 | }; 48 | 49 | 50 | struct symbol_table { 51 | struct symbol *addr_to_symbol[0x10000]; 52 | char *name_area; 53 | int name_area_free; 54 | char *name_area_next; 55 | }; 56 | 57 | 58 | struct breakpoint { 59 | target_addr_t addr; 60 | int flags; 61 | int count; 62 | }; 63 | 64 | 65 | #define FC_TAIL_CALL 0x1 66 | 67 | struct function_call { 68 | target_addr_t entry_point; 69 | struct cpu_regs entry_regs; 70 | int flags; 71 | }; 72 | 73 | void add_named_symbol (const char *id, target_addr_t value, const char *filename); 74 | struct x_symbol * find_symbol (target_addr_t value); 75 | void monitor_branch (void); 76 | void monitor_call (unsigned int flags); 77 | void monitor_return (void); 78 | const char * monitor_addr_name (target_addr_t addr); 79 | const char * absolute_addr_name (unsigned long addr); 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /prog/hello.c: -------------------------------------------------------------------------------- 1 | 2 | /* Needed for write() */ 3 | #include 4 | 5 | int main (void) 6 | { 7 | /* We don't have printf() working yet, so we have to 8 | * use the UNIX-like system calls. */ 9 | write (1, "Hello, World\n", 13); 10 | return (0); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /prog/infloop.c: -------------------------------------------------------------------------------- 1 | 2 | void main (void) 3 | { 4 | for (;;) 5 | { 6 | __builtin_nop (); 7 | __builtin_nop (); 8 | __builtin_nop (); 9 | __builtin_nop (); 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /prog/string.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main (void) 6 | { 7 | if (strlen ("Testing") != 7) 8 | return 1; 9 | 10 | if (strlen ("") != 0) 11 | return 2; 12 | 13 | write (1, "Test passed.\n", 13); 14 | return 0; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "machine.h" 27 | 28 | /* Emulate a serial port. Basically this driver can be used for any byte-at-a-time 29 | input/output interface. */ 30 | struct serial_port 31 | { 32 | unsigned int ctrl; 33 | unsigned int status; 34 | int fin; 35 | int fout; 36 | }; 37 | 38 | /* The I/O registers exposed by this driver */ 39 | #define SER_DATA 0 /* Data input/output */ 40 | #define SER_CTL_STATUS 1 /* Control (write) and status (read) */ 41 | #define SER_CTL_ASYNC 0x1 /* Enable async mode (more realistic) */ 42 | #define SER_CTL_RESET 0x2 /* Reset device */ 43 | 44 | #define SER_STAT_READOK 0x1 45 | #define SER_STAT_WRITEOK 0x2 46 | 47 | void serial_update (struct serial_port *port) 48 | { 49 | fd_set infds, outfds; 50 | struct timeval timeout; 51 | int rc; 52 | 53 | FD_ZERO (&infds); 54 | FD_SET (port->fin, &infds); 55 | FD_ZERO (&outfds); 56 | FD_SET (port->fout, &outfds); 57 | timeout.tv_sec = 0; 58 | timeout.tv_usec = 0; 59 | rc = select (2, &infds, &outfds, NULL, &timeout); 60 | if (FD_ISSET (port->fin, &infds)) 61 | port->status |= SER_STAT_READOK; 62 | else 63 | port->status &= ~SER_STAT_READOK; 64 | if (FD_ISSET (port->fout, &outfds)) 65 | port->status |= SER_STAT_WRITEOK; 66 | else 67 | port->status &= ~SER_STAT_WRITEOK; 68 | } 69 | 70 | U8 serial_read (struct hw_device *dev, unsigned long addr) 71 | { 72 | struct serial_port *port = (struct serial_port *)dev->priv; 73 | serial_update (port); 74 | switch (addr) 75 | { 76 | case SER_DATA: 77 | { 78 | U8 val; 79 | if (!(port->status & SER_STAT_READOK)) 80 | return 0xFF; 81 | read (port->fin, &val, 1); 82 | return val; 83 | } 84 | case SER_CTL_STATUS: 85 | return port->status; 86 | } 87 | } 88 | 89 | void serial_write (struct hw_device *dev, unsigned long addr, U8 val) 90 | { 91 | struct serial_port *port = (struct serial_port *)dev->priv; 92 | switch (addr) 93 | { 94 | case SER_DATA: 95 | { 96 | U8 v = val; 97 | write (port->fout, &v, 1); 98 | break; 99 | } 100 | case SER_CTL_STATUS: 101 | port->ctrl = val; 102 | break; 103 | } 104 | } 105 | 106 | void serial_reset (struct hw_device *dev) 107 | { 108 | struct serial_port *port = (struct serial_port *)dev->priv; 109 | port->ctrl = 0; 110 | port->status = 0; 111 | } 112 | 113 | struct hw_class serial_class = 114 | { 115 | .readonly = 0, 116 | .reset = serial_reset, 117 | .read = serial_read, 118 | .write = serial_write, 119 | }; 120 | 121 | extern U8 null_read (struct hw_device *dev, unsigned long addr); 122 | 123 | 124 | struct hw_device *serial_create (void) 125 | { 126 | struct serial_port *port = malloc (sizeof (struct serial_port)); 127 | port->fin = STDIN_FILENO; 128 | port->fout = STDOUT_FILENO; 129 | return device_attach (&serial_class, 4, port); 130 | } 131 | 132 | struct hw_device *hostfile_create (const char *filename, int flags) 133 | { 134 | struct serial_port *port = malloc (sizeof (struct serial_port)); 135 | port->fin = port->fout = open (filename, O_CREAT | flags); 136 | return device_attach (&serial_class, 4, port); 137 | } 138 | 139 | -------------------------------------------------------------------------------- /symtab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2008 by Brian Dominy 3 | * 4 | * This file is part of the Portable 6809 Simulator. 5 | * 6 | * The Simulator is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * The Simulator is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this software; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "6809.h" 22 | 23 | /* A pointer to the current stringspace */ 24 | struct stringspace *current_stringspace; 25 | 26 | /* Symbol table for program variables (taken from symbol file) */ 27 | struct symtab program_symtab; 28 | 29 | /* Symbol table for internal variables. Works identically to the 30 | above but in a different namespace */ 31 | struct symtab internal_symtab; 32 | 33 | /* Symbol table for the 'autocomputed virtuals'. The values 34 | kept in the table are pointers to functions that compute the 35 | values, allowing for dynamic variables. */ 36 | struct symtab auto_symtab; 37 | 38 | 39 | /** 40 | * Create a new stringspace, which is just a buffer that 41 | * holds strings. 42 | */ 43 | struct stringspace *stringspace_create (void) 44 | { 45 | struct stringspace *ss = malloc (sizeof (struct stringspace)); 46 | ss->used = 0; 47 | return ss; 48 | } 49 | 50 | 51 | /** 52 | * Copy a string into the stringspace. This keeps it around 53 | * permanently; the caller is allowed to free the string 54 | * afterwards. 55 | */ 56 | char *stringspace_copy (const char *string) 57 | { 58 | unsigned int len = strlen (string) + 1; 59 | char *result; 60 | 61 | if (current_stringspace->used + len > MAX_STRINGSPACE) 62 | current_stringspace = stringspace_create (); 63 | 64 | result = current_stringspace->space + current_stringspace->used; 65 | strcpy (result, string); 66 | current_stringspace->used += len; 67 | return result; 68 | } 69 | 70 | 71 | unsigned int sym_hash_name (const char *name) 72 | { 73 | unsigned int hash = *name & 0x1F; 74 | if (*name++ != '\0') 75 | { 76 | hash = (hash << 11) + (544 * *name); 77 | if (*name++ != '\0') 78 | { 79 | hash = (hash << 5) + (17 * *name); 80 | } 81 | } 82 | return hash % MAX_SYMBOL_HASH; 83 | } 84 | 85 | 86 | unsigned int sym_hash_value (unsigned long value) 87 | { 88 | return value % MAX_SYMBOL_HASH; 89 | } 90 | 91 | 92 | /** 93 | * Lookup the symbol table entry for 'name'. 94 | * Returns NULL if the symbol is not defined. 95 | * If VALUE is not-null, the value is also copied there. 96 | */ 97 | struct symbol *sym_find1 (struct symtab *symtab, 98 | const char *name, unsigned long *value, 99 | unsigned int type) 100 | { 101 | unsigned int hash = sym_hash_name (name); 102 | 103 | /* Search starting in the current symbol table, and if that fails, 104 | * try its parent tables. */ 105 | while (symtab != NULL) 106 | { 107 | /* Find the list of elements that hashed to this string. */ 108 | struct symbol *chain = symtab->syms_by_name[hash]; 109 | 110 | /* Scan the list for an exact match, and return it. */ 111 | while (chain != NULL) 112 | { 113 | if (!strcmp (name, chain->name)) 114 | { 115 | if (type && (chain->type != type)) 116 | return NULL; 117 | if (value) 118 | *value = chain->value; 119 | return chain; 120 | } 121 | chain = chain->name_chain; 122 | } 123 | symtab = symtab->parent; 124 | } 125 | 126 | return NULL; 127 | } 128 | 129 | 130 | /** 131 | * Lookup the symbol 'name'. 132 | * Returns 0 if the symbol exists (and optionally stores its value 133 | * in *value if not NULL), or -1 if it does not exist. 134 | */ 135 | int sym_find (struct symtab *symtab, 136 | const char *name, unsigned long *value, unsigned int type) 137 | { 138 | return sym_find1 (symtab, name, value, type) ? 0 : -1; 139 | } 140 | 141 | 142 | const char *sym_lookup (struct symtab *symtab, unsigned long value) 143 | { 144 | unsigned int hash = sym_hash_value (value); 145 | 146 | while (symtab != NULL) 147 | { 148 | struct symbol *chain = symtab->syms_by_value[hash]; 149 | while (chain != NULL) 150 | { 151 | if (value == chain->value) 152 | return chain->name; 153 | chain = chain->value_chain; 154 | } 155 | symtab = symtab->parent; 156 | } 157 | return NULL; 158 | } 159 | 160 | 161 | struct symbol *sym_add (struct symtab *symtab, 162 | const char *name, unsigned long value, unsigned int type) 163 | { 164 | unsigned int hash; 165 | struct symbol *s, *chain; 166 | 167 | s = malloc (sizeof (struct symbol)); 168 | s->name = stringspace_copy (name); 169 | s->value = value; 170 | s->type = type; 171 | s->ty.format = 0; 172 | s->ty.size = 0; 173 | 174 | hash = sym_hash_name (name); 175 | chain = symtab->syms_by_name[hash]; 176 | s->name_chain = chain; 177 | symtab->syms_by_name[hash] = s; 178 | 179 | hash = sym_hash_value (value); 180 | chain = symtab->syms_by_value[hash]; 181 | s->value_chain = chain; 182 | symtab->syms_by_value[hash] = s; 183 | 184 | return s; 185 | } 186 | 187 | 188 | void sym_set (struct symtab *symtab, 189 | const char *name, unsigned long value, unsigned int type) 190 | { 191 | struct symbol * s = sym_find1 (symtab, name, NULL, type); 192 | if (s) 193 | s->value = value; 194 | else 195 | sym_add (symtab, name, value, type); 196 | } 197 | 198 | 199 | void for_each_var (void (*cb) (struct symbol *, unsigned int size)) 200 | { 201 | struct symtab *symtab = &program_symtab; 202 | absolute_address_t addr; 203 | const char *id; 204 | struct symbol *sym; 205 | unsigned int devid = 1; /* TODO */ 206 | 207 | for (addr = devid << 28; addr < (devid << 28) + 0x2000; addr++) 208 | { 209 | id = sym_lookup (symtab, addr); 210 | if (id) 211 | { 212 | sym = sym_find1 (symtab, id, NULL, 0); 213 | printf ("%-20.20s %8lX %d\n", id, addr, sym->ty.size); 214 | } 215 | } 216 | } 217 | 218 | void symtab_init (struct symtab *symtab) 219 | { 220 | memset (symtab, 0, sizeof (struct symtab)); 221 | } 222 | 223 | 224 | void symtab_reset (struct symtab *symtab) 225 | { 226 | /* TODO */ 227 | symtab_init (symtab); 228 | } 229 | 230 | 231 | void sym_init (void) 232 | { 233 | current_stringspace = stringspace_create (); 234 | 235 | /* Initialize three symbol tables for general use. 236 | * The program_symtab stores names found in the program's 237 | * symbol table/map file. The auto symtab has special reserved 238 | * names. */ 239 | symtab_init (&program_symtab); 240 | symtab_init (&internal_symtab); 241 | symtab_init (&auto_symtab); 242 | } 243 | 244 | -------------------------------------------------------------------------------- /timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include "machine.h" 23 | 24 | /* A hardware timer counts CPU cycles and can generate interrupts periodically. */ 25 | struct hwtimer 26 | { 27 | int count; /* The current value of the timer */ 28 | unsigned int reload; /* Value to reload into the timer when it reaches zero */ 29 | unsigned int resolution; /* Resolution of CPU registers (cycles/tick) */ 30 | unsigned int flags; 31 | unsigned long prev_cycles; 32 | struct hw_device *int_dev; /* Which interrupt mux we use */ 33 | unsigned int int_line; /* Which interrupt to signal */ 34 | }; 35 | 36 | /* The I/O registers exposed by this driver */ 37 | #define HWT_COUNT 0 /* The 8-bit timer counter */ 38 | #define HWT_RELOAD 1 /* The 8-bit reload counter */ 39 | #define HWT_FLAGS 2 /* Misc. flags */ 40 | #define HWTF_INT 0x80 /* Generate interrupt at zero */ 41 | 42 | 43 | /* 44 | * Called by the system to indicate that some number of CPU cycles have passed. 45 | */ 46 | void hwtimer_decrement (struct hwtimer *timer, unsigned int cycles) 47 | { 48 | /* If either the counter or the reload register is nonzero, the timer 49 | is considered running. Otherwise, nothing to do */ 50 | if (!timer->count && !timer->reload) 51 | return; 52 | 53 | /* Decrement the counter. Is it zero/negative? */ 54 | timer->count -= cycles; 55 | if (timer->count <= 0) 56 | { 57 | /* If interrupt is configured and enabled, generate one now */ 58 | if (timer->int_dev && timer->flags & HWTF_INT) 59 | { 60 | imux_assert (timer->int_dev, timer->int_line); 61 | } 62 | 63 | /* If it is negative, we need to make it positive again. 64 | If reload is nonzero, add that, to simulate the timer "wrapping". 65 | Otherwise, fix it at zero. */ 66 | if (timer->count < 0) 67 | { 68 | if (timer->reload > 0) 69 | { 70 | timer->count += timer->reload; 71 | /* Note: if timer->count is still negative, the reload value 72 | is lower than the frequency at which the system is updating the 73 | timers, and we would need to simulate two interrupts here 74 | perhaps. For later. */ 75 | if (timer->count < 0) 76 | sim_error ("timer count = %d, reload = %d\n", timer->count, timer->reload); 77 | } 78 | else 79 | { 80 | timer->count = 0; 81 | } 82 | } 83 | } 84 | } 85 | 86 | void hwtimer_update (struct hw_device *dev) 87 | { 88 | struct hwtimer *timer = (struct hwtimer *)dev->priv; 89 | unsigned long cycles = get_cycles (); 90 | hwtimer_decrement (timer, cycles - timer->prev_cycles); 91 | timer->prev_cycles = cycles; 92 | } 93 | 94 | 95 | U8 hwtimer_read (struct hw_device *dev, unsigned long addr) 96 | { 97 | struct hwtimer *timer = (struct hwtimer *)dev->priv; 98 | switch (addr) 99 | { 100 | case HWT_COUNT: 101 | return timer->count / timer->resolution; 102 | case HWT_RELOAD: 103 | return timer->reload / timer->resolution; 104 | case HWT_FLAGS: 105 | return timer->flags; 106 | } 107 | } 108 | 109 | void hwtimer_write (struct hw_device *dev, unsigned long addr, U8 val) 110 | { 111 | struct hwtimer *timer = (struct hwtimer *)dev->priv; 112 | switch (addr) 113 | { 114 | case HWT_COUNT: 115 | timer->count = val * timer->resolution; 116 | break; 117 | case HWT_RELOAD: 118 | timer->reload = val * timer->resolution; 119 | break; 120 | case HWT_FLAGS: 121 | timer->flags = val; 122 | break; 123 | } 124 | } 125 | 126 | void hwtimer_reset (struct hw_device *dev) 127 | { 128 | struct hwtimer *timer = (struct hwtimer *)dev->priv; 129 | timer->count = 0; 130 | timer->flags = 0; 131 | timer->resolution = 128; 132 | timer->prev_cycles = get_cycles (); 133 | } 134 | 135 | void oscillator_reset (struct hw_device *dev) 136 | { 137 | struct hwtimer *timer = (struct hwtimer *)dev->priv; 138 | hwtimer_reset (dev); 139 | timer->count = timer->reload; 140 | if (timer->int_dev) 141 | timer->flags |= HWTF_INT; 142 | } 143 | 144 | struct hw_class hwtimer_class = 145 | { 146 | .readonly = 0, 147 | .reset = hwtimer_reset, 148 | .read = hwtimer_read, 149 | .write = hwtimer_write, 150 | .update = hwtimer_update, 151 | }; 152 | 153 | struct hw_device *hwtimer_create (struct hw_device *int_dev, unsigned int int_line) 154 | { 155 | struct hwtimer *timer = malloc (sizeof (struct hwtimer)); 156 | timer->reload = 0; 157 | timer->int_dev = int_dev; 158 | timer->int_line = int_line; 159 | return device_attach (&hwtimer_class, 16, timer); /* 16 = sizeof I/O window */ 160 | } 161 | 162 | struct hw_class oscillator_class = 163 | { 164 | .readonly = 0, 165 | .reset = oscillator_reset, 166 | .read = NULL, 167 | .write = NULL, 168 | .update = hwtimer_update, 169 | }; 170 | 171 | struct hw_device *oscillator_create (struct hw_device *int_dev, unsigned int int_line) 172 | { 173 | struct hwtimer *timer = malloc (sizeof (struct hwtimer)); 174 | timer->reload = 2048; /* cycles per pulse */ 175 | timer->int_dev = int_dev; 176 | timer->int_line = int_line; 177 | return device_attach (&oscillator_class, 0, timer); 178 | } 179 | -------------------------------------------------------------------------------- /wpc-run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | m6809-run -s wpc -I 2049 -b -C -d -m -1 $* 3 | -------------------------------------------------------------------------------- /wpc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2008 by Brian Dominy 3 | * 4 | * This file is part of GCC6809. 5 | * 6 | * GCC6809 is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * GCC6809 is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GCC6809; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "6809.h" 22 | #ifdef HAVE_SYS_TIME_H 23 | # include 24 | #else 25 | #error 26 | #endif 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "wpclib.h" 32 | 33 | #define WPC_RAM_BASE 0x0000 34 | #define WPC_RAM_SIZE 0x2000 35 | #define WPC_ROM_SIZE 0x100000 36 | #define WPC_PAGED_REGION 0x4000 37 | #define WPC_PAGED_SIZE 0x4000 38 | #define WPC_FIXED_REGION 0x8000 39 | #define WPC_FIXED_SIZE 0x8000 40 | 41 | /* The register set of the WPC ASIC */ 42 | #define WPC_ASIC_BASE 0x3c00 43 | 44 | #define WPC_DMD_LOW_BASE 0x3800 45 | #define WPC_DMD_HIGH_BASE 0x3A00 46 | 47 | #define WPC_DEBUG_DATA_PORT 0x3D60 48 | #define WPC_DEBUG_CONTROL_PORT 0x3D61 49 | #define WPC_DEBUG_WRITE_READY 0x1 50 | #define WPC_DEBUG_READ_READY 0x2 51 | #define WPC_PINMAME_CYCLE_COUNT 0x3D62 52 | #define WPC_PINMAME_FUNC_ENTRY_HI 0x3D63 53 | #define WPC_PINMAME_FUNC_ENTRY_LO 0x3D64 54 | #define WPC_PINMAME_FUNC_EXIT_HI 0x3D65 55 | #define WPC_PINMAME_FUNC_EXIT_LO 0x3D66 56 | #define WPC_SERIAL_CONTROL_PORT 0x3E66 57 | #define WPC_SERIAL_DATA_PORT 0x3E67 58 | 59 | #define WPC_DMD_3200_PAGE 0x3FB8 60 | #define WPC_DMD_3000_PAGE 0x3FB9 61 | #define WPC_DMD_3600_PAGE 0x3FBA 62 | #define WPC_DMD_3400_PAGE 0x3FBB 63 | #define WPC_DMD_HIGH_PAGE 0x3FBC 64 | #define WPC_DMD_FIRQ_ROW_VALUE 0x3FBD 65 | #define WPC_DMD_LOW_PAGE 0x3FBE 66 | #define WPC_DMD_ACTIVE_PAGE 0x3FBF 67 | #define WPC_SERIAL_STATUS_PORT 0x3FC0 68 | #define WPC_PARALLEL_DATA_PORT 0x3FC1 69 | #define WPC_PARALLEL_STROBE_PORT 0x3FC2 70 | #define WPC_SERIAL_DATA_OUTPUT 0x3FC3 71 | #define WPC_SERIAL_CONTROL_OUTPUT 0x3FC4 72 | #define WPC_SERIAL_BAUD_SELECT 0x3FC5 73 | #define WPC_TICKET_DISPENSE 0x3FC6 74 | #define WPC_DCS_SOUND_DATA_OUT 0x3FD0 75 | #define WPC_DCS_SOUND_DATA_IN 0x3FD1 76 | #define WPC_DCS_SOUND_RESET 0x3FD2 77 | #define WPC_DCS_SOUND_DATA_READY 0x3FD3 78 | #define WPC_FLIPTRONIC_PORT_A 0x3FD4 79 | #define WPC_FLIPTRONIC_PORT_B 0x3FD5 80 | #define WPCS_DATA 0x3FDC 81 | #define WPCS_CONTROL_STATUS 0x3FDD 82 | #define WPC_SOL_FLASH2_OUTPUT 0x3FE0 83 | #define WPC_SOL_HIGHPOWER_OUTPUT 0x3FE1 84 | #define WPC_SOL_FLASH1_OUTPUT 0x3FE2 85 | #define WPC_SOL_LOWPOWER_OUTPUT 0x3FE3 86 | #define WPC_LAMP_ROW_OUTPUT 0x3FE4 87 | #define WPC_LAMP_COL_STROBE 0x3FE5 88 | #define WPC_GI_TRIAC 0x3FE6 89 | #define WPC_SW_JUMPER_INPUT 0x3FE7 90 | #define WPC_SW_CABINET_INPUT 0x3FE8 91 | #define WPC_SW_ROW_INPUT 0x3FE9 /* WPC */ 92 | #define WPC_SW_COL_STROBE 0x3FEA /* WPC */ 93 | #define WPCS_PIC_READ 0x3FE9 /* WPCS, WPC95 */ 94 | #define WPCS_PIC_WRITE 0x3FEA /* WPCS, WPC95 */ 95 | #if (MACHINE_DMD == 0) 96 | #define WPC_ALPHA_POS 0x3FEB 97 | #define WPC_ALPHA_ROW1 0x3FEC 98 | #else 99 | #define WPC_EXTBOARD1 0x3FEB 100 | #define WPC_EXTBOARD2 0x3FEC 101 | #define WPC_EXTBOARD3 0x3FED 102 | #endif 103 | #define WPC95_FLIPPER_COIL_OUTPUT 0x3FEE /* WPC95 */ 104 | #define WPC95_FLIPPER_SWITCH_INPUT 0x3FEF /* WPC95 */ 105 | #if (MACHINE_DMD == 0) 106 | #define WPC_ALPHA_ROW2 0x3FEE 107 | #else 108 | #endif 109 | #define WPC_LEDS 0x3FF2 110 | #define WPC_RAM_BANK 0x3FF3 /* WPC95 */ 111 | #define WPC_SHIFTADDR 0x3FF4 112 | #define WPC_SHIFTBIT 0x3FF6 113 | #define WPC_SHIFTBIT2 0x3FF7 114 | #define WPC_PERIPHERAL_TIMER_FIRQ_CLEAR 0x3FF8 115 | #define WPC_ROM_LOCK 0x3FF9 116 | #define WPC_CLK_HOURS_DAYS 0x3FFA 117 | #define WPC_CLK_MINS 0x3FFB 118 | #define WPC_ROM_BANK 0x3FFC 119 | #define WPC_RAM_LOCK 0x3FFD 120 | #define WPC_RAM_LOCKSIZE 0x3FFE 121 | #define WPC_ZEROCROSS_IRQ_CLEAR 0x3FFF 122 | 123 | /** 124 | * The 'wpc_asic' struct holds all of the state 125 | * of the ASIC. There is a single instance of this, 126 | * named 'the_wpc', and it is pointed to by the 127 | * global 'wpc'. Only one ASIC can be defined at 128 | * a time. 129 | */ 130 | struct wpc_asic 131 | { 132 | struct hw_device *rom_dev; 133 | struct hw_device *ram_dev; 134 | struct hw_device *dmd_dev; 135 | 136 | U8 led; 137 | U8 rombank; 138 | U8 ram_unlocked; 139 | U8 ram_lock_size; 140 | U16 shiftaddr; 141 | U16 shiftbit; 142 | U8 lamp_strobe; 143 | U8 lamp_mx[8]; 144 | U8 sols[48]; 145 | U8 switch_strobe; 146 | U8 switch_mx[10]; 147 | U8 opto_mx[10]; 148 | U8 dmd_maps[2]; 149 | 150 | unsigned int dmd_phase; 151 | U8 dmd_visibles[3]; 152 | U8 dmd_last_visibles[3]; 153 | 154 | int curr_sw; 155 | int curr_sw_time; 156 | int wdog_timer; 157 | } the_wpc; 158 | 159 | 160 | struct wpc_asic *wpc = NULL; 161 | 162 | int wpc_sock; 163 | 164 | 165 | static int wpc_console_inited = 0; 166 | 167 | static U8 wpc_get_console_state (void) 168 | { 169 | fd_set fds; 170 | struct timeval timeout; 171 | U8 rc = WPC_DEBUG_WRITE_READY; 172 | 173 | if (!wpc_console_inited) 174 | rc |= WPC_DEBUG_READ_READY; 175 | 176 | #if 1 177 | return rc; 178 | #endif 179 | 180 | FD_ZERO (&fds); 181 | FD_SET (0, &fds); 182 | 183 | timeout.tv_sec = 0; 184 | timeout.tv_usec = 0; 185 | if (select (1, &fds, NULL, NULL, &timeout)) 186 | rc |= WPC_DEBUG_READ_READY; 187 | 188 | return rc; 189 | } 190 | 191 | 192 | static U8 wpc_console_read (void) 193 | { 194 | int rc; 195 | U8 c = 0; 196 | 197 | if (!wpc_console_inited) 198 | { 199 | wpc_console_inited = 1; 200 | return 0; 201 | } 202 | 203 | rc = read (0, &c, 1); 204 | return c; 205 | } 206 | 207 | 208 | static void wpc_console_write (U8 val) 209 | { 210 | putchar (val); 211 | fflush (stdout); 212 | } 213 | 214 | 215 | static int scanbit (U8 val) 216 | { 217 | if (val & 0x80) return 7; 218 | else if (val & 0x40) return 6; 219 | else if (val & 0x20) return 5; 220 | else if (val & 0x10) return 4; 221 | else if (val & 0x08) return 3; 222 | else if (val & 0x04) return 2; 223 | else if (val & 0x02) return 1; 224 | else if (val & 0x01) return 0; 225 | else return -1; 226 | } 227 | 228 | 229 | unsigned int wpc_read_switch (int num) 230 | { 231 | unsigned int val; 232 | val = wpc->switch_mx[num / 8] & (1 << (num % 8)); 233 | return val ? 1 : 0; 234 | } 235 | 236 | void wpc_write_switch (int num, int flag) 237 | { 238 | unsigned int col, val; 239 | 240 | col = num / 8; 241 | val = 1 << (num % 8); 242 | 243 | #if 0 244 | if (wpc->opto_mx[col] & val) 245 | flag = !flag; 246 | #endif 247 | 248 | wpc->switch_mx[col] &= ~val; 249 | if (flag) 250 | wpc->switch_mx[col] |= val; 251 | } 252 | 253 | void wpc_press_switch (int num, int delay) 254 | { 255 | wpc_write_switch (num, 1); 256 | wpc->curr_sw = num; 257 | wpc->curr_sw_time = delay; 258 | } 259 | 260 | unsigned int wpc_read_switch_column (int col) 261 | { 262 | unsigned int val = 0; 263 | int row; 264 | for (row = 0; row < 8; row++) 265 | if (wpc_read_switch (col * 8 + row)) 266 | val |= (1 << row); 267 | return val; 268 | } 269 | 270 | void wpc_write_lamp (int num, int flag) 271 | { 272 | } 273 | 274 | 275 | void wpc_write_sols (int first, U8 val) 276 | { 277 | int i; 278 | for (i=0; i < 8; i++) 279 | { 280 | wpc->sols[first+i] = (val & (1 << i)) ? 1 : 0; 281 | } 282 | } 283 | 284 | 285 | void wpc_dmd_set_visible (U8 val) 286 | { 287 | char *p; 288 | struct wpc_message msg; 289 | int rc; 290 | int i, n; 291 | static unsigned long last_firq_time = 0; 292 | unsigned long now; 293 | static int no_change_count = 0; 294 | 295 | now = get_cycles (); 296 | if (now - last_firq_time <= 1850 * 8) 297 | { 298 | //printf ("%02X ignored.\n", val); 299 | return; 300 | } 301 | else if (now - last_firq_time >= 1850 * 8 * 5) 302 | { 303 | memset (wpc->dmd_visibles, val, 3); 304 | wpc->dmd_phase = 0; 305 | } 306 | else 307 | { 308 | wpc->dmd_visibles[wpc->dmd_phase++] = val; 309 | if (wpc->dmd_phase == 3) 310 | wpc->dmd_phase = 0; 311 | } 312 | 313 | last_firq_time = now; 314 | 315 | #if 0 316 | printf ("%02X %f\n", val, get_cycles () / 1952.0); 317 | #endif 318 | 319 | if (!memcmp (wpc->dmd_visibles, wpc->dmd_last_visibles, 3) 320 | && (++no_change_count < 100)) 321 | return; 322 | 323 | no_change_count = 0; 324 | #if 0 325 | printf ("%02X %02X %02X\n", 326 | wpc->dmd_visibles[0], 327 | wpc->dmd_visibles[1], 328 | wpc->dmd_visibles[2]); 329 | #endif 330 | memcpy (wpc->dmd_last_visibles, wpc->dmd_visibles, 3); 331 | 332 | /* Send updated page contents */ 333 | wpc_msg_init (CODE_DMD_PAGE, &msg); 334 | for (i=0; i < 3; i++) 335 | { 336 | p = wpc->dmd_dev->priv + wpc->dmd_visibles[i] * 512; 337 | msg.u.dmdpage.phases[i].page = wpc->dmd_visibles[i]; 338 | memcpy (&msg.u.dmdpage.phases[i].data, p, 512); 339 | } 340 | msg.len = sizeof (struct _dmdpage_info); 341 | wpc_msg_send (wpc_sock, 9000 ^ 1, &msg); 342 | 343 | /* Send status of which pages are visible now */ 344 | wpc_msg_init (CODE_DMD_VISIBLE, &msg); 345 | for (i=0; i < 3; i++) 346 | msg.u.dmdvisible.phases[i] = wpc->dmd_visibles[i]; 347 | msg.len = sizeof (struct _dmdvisible_info); 348 | wpc_msg_send (wpc_sock, 9000 ^ 1, &msg); 349 | } 350 | 351 | 352 | void wpc_keypoll (void) 353 | { 354 | fd_set fds; 355 | struct timeval timeout; 356 | int rc; 357 | unsigned char c; 358 | 359 | FD_ZERO (&fds); 360 | FD_SET (0, &fds); 361 | 362 | timeout.tv_sec = 0; 363 | timeout.tv_usec = 0; 364 | if (select (1, &fds, NULL, NULL, &timeout)) 365 | { 366 | rc = read (0, &c, 1); 367 | 368 | #define BUTTON_DURATION 200 369 | switch (c) 370 | { 371 | case '7': 372 | wpc_press_switch (4, BUTTON_DURATION); 373 | break; 374 | case '8': 375 | wpc_press_switch (5, BUTTON_DURATION); 376 | break; 377 | case '9': 378 | wpc_press_switch (6, BUTTON_DURATION); 379 | break; 380 | case '0': 381 | wpc_press_switch (7, BUTTON_DURATION); 382 | break; 383 | case ',': 384 | wpc_press_switch (75, BUTTON_DURATION); 385 | break; 386 | case '.': 387 | wpc_press_switch (73, BUTTON_DURATION); 388 | break; 389 | default: 390 | printf ("wpc: invalid character '%c'\n", c); 391 | break; 392 | } 393 | } 394 | } 395 | 396 | 397 | 398 | U8 wpc_asic_read (struct hw_device *dev, unsigned long addr) 399 | { 400 | U8 val; 401 | 402 | switch (addr + WPC_ASIC_BASE) 403 | { 404 | case WPC_LEDS: 405 | val = wpc->led; 406 | break; 407 | 408 | case WPC_ROM_BANK: 409 | val = wpc->rombank; 410 | break; 411 | 412 | case WPC_DEBUG_CONTROL_PORT: 413 | val = wpc_get_console_state (); 414 | break; 415 | 416 | case WPC_DEBUG_DATA_PORT: 417 | val = wpc_console_read (); 418 | break; 419 | 420 | case WPC_SHIFTADDR: 421 | val = wpc->shiftaddr >> 8; 422 | break; 423 | 424 | case WPC_SHIFTADDR+1: 425 | val = (wpc->shiftaddr & 0xFF) + (wpc->shiftbit / 8); 426 | break; 427 | 428 | case WPC_SHIFTBIT: 429 | val = 1 << (wpc->shiftbit % 8); 430 | break; 431 | 432 | case WPC_SW_ROW_INPUT: 433 | { 434 | /* Handle WPC and WPC-S machines differently */ 435 | if (wpc->switch_strobe >= 0x16 && wpc->switch_strobe <= 0x1F) 436 | val = wpc_read_switch_column (wpc->switch_strobe - 0x16 + 1); 437 | else 438 | val = wpc_read_switch_column (1 + scanbit (wpc->switch_strobe)); 439 | break; 440 | } 441 | 442 | case WPC_SW_JUMPER_INPUT: 443 | val = 0x55; 444 | break; 445 | 446 | case WPC_SW_CABINET_INPUT: 447 | val = wpc_read_switch_column (0); 448 | break; 449 | 450 | case WPC_FLIPTRONIC_PORT_A: 451 | case WPC_FLIPTRONIC_PORT_B: 452 | case WPC95_FLIPPER_SWITCH_INPUT: 453 | val = wpc_read_switch_column (9); 454 | break; 455 | 456 | default: 457 | val = 0; 458 | break; 459 | } 460 | //printf (">>> ASIC read %04X -> %02X\n", addr + WPC_ASIC_BASE, val); 461 | return val; 462 | } 463 | 464 | 465 | /** 466 | * Enforce the current read-only area of RAM. 467 | */ 468 | void wpc_update_ram (void) 469 | { 470 | unsigned int size_writable = WPC_RAM_SIZE; 471 | 472 | if (!wpc->ram_unlocked) 473 | { 474 | switch (wpc->ram_lock_size) 475 | { 476 | default: 477 | break; 478 | case 0xF: 479 | size_writable -= 256; 480 | break; 481 | case 0x7: 482 | size_writable -= 512; 483 | case 0x3: 484 | size_writable -= 1024; 485 | break; 486 | case 0x1: 487 | size_writable -= 2048; 488 | break; 489 | case 0: 490 | size_writable -= 4096; 491 | break; 492 | } 493 | } 494 | 495 | bus_map (WPC_RAM_BASE, wpc->ram_dev->devid, 0, size_writable, MAP_READWRITE); 496 | if (size_writable < WPC_RAM_SIZE) 497 | bus_map (WPC_RAM_BASE + size_writable, wpc->ram_dev->devid, size_writable, 498 | WPC_RAM_SIZE - size_writable, MAP_READABLE); 499 | } 500 | 501 | 502 | void wpc_set_rom_page (unsigned char val) 503 | { 504 | bus_map (WPC_PAGED_REGION, 2, val * WPC_PAGED_SIZE, WPC_PAGED_SIZE, MAP_READABLE); 505 | } 506 | 507 | void wpc_set_dmd_page (unsigned int map, unsigned char val) 508 | { 509 | wpc->dmd_maps[map] = val; 510 | bus_map (0x3800 + map * 0x200, 3, val * 0x200, 0x200, MAP_READWRITE); 511 | } 512 | 513 | 514 | void wpc_asic_write (struct hw_device *dev, unsigned long addr, U8 val) 515 | { 516 | switch (addr + WPC_ASIC_BASE) 517 | { 518 | case WPC_DMD_LOW_PAGE: 519 | wpc_set_dmd_page (0, val); 520 | break; 521 | 522 | case WPC_DMD_HIGH_PAGE: 523 | wpc_set_dmd_page (1, val); 524 | break; 525 | 526 | case WPC_DMD_FIRQ_ROW_VALUE: 527 | break; 528 | 529 | case WPC_DMD_ACTIVE_PAGE: 530 | wpc_dmd_set_visible (val); 531 | break; 532 | 533 | case WPC_LEDS: 534 | wpc->led = val; 535 | break; 536 | 537 | case WPC_ZEROCROSS_IRQ_CLEAR: 538 | wpc->wdog_timer++; 539 | break; 540 | 541 | case WPC_ROM_BANK: 542 | wpc->rombank = val; 543 | wpc_set_rom_page (val); 544 | break; 545 | 546 | case WPC_DEBUG_DATA_PORT: 547 | wpc_console_write (val); 548 | break; 549 | 550 | case WPC_RAM_LOCK: 551 | wpc->ram_unlocked = val; 552 | wpc_update_ram (); 553 | break; 554 | 555 | case WPC_RAM_LOCKSIZE: 556 | wpc->ram_lock_size = val; 557 | wpc_update_ram (); 558 | break; 559 | 560 | case WPC_SHIFTADDR: 561 | wpc->shiftaddr &= 0x00FF; 562 | wpc->shiftaddr |= val << 8; 563 | break; 564 | 565 | case WPC_SHIFTADDR+1: 566 | wpc->shiftaddr &= 0xFF00; 567 | wpc->shiftaddr |= val; 568 | break; 569 | 570 | case WPC_SHIFTBIT: 571 | wpc->shiftbit = val; 572 | break; 573 | 574 | case WPC_LAMP_ROW_OUTPUT: 575 | wpc->lamp_mx[scanbit (wpc->lamp_strobe)] = val; 576 | break; 577 | 578 | case WPC_LAMP_COL_STROBE: 579 | wpc->lamp_strobe = val; 580 | break; 581 | 582 | case WPC_SW_COL_STROBE: 583 | wpc->switch_strobe = val; 584 | break; 585 | 586 | case WPC_SOL_FLASH2_OUTPUT: 587 | case WPC_SOL_HIGHPOWER_OUTPUT: 588 | case WPC_SOL_FLASH1_OUTPUT: 589 | case WPC_SOL_LOWPOWER_OUTPUT: 590 | if (val != 0) 591 | printf (">>> ASIC write %04X %02X\n", addr + WPC_ASIC_BASE, val); 592 | break; 593 | 594 | default: 595 | break; 596 | } 597 | //printf (">>> ASIC write %04X %02X\n", addr + WPC_ASIC_BASE, val); 598 | } 599 | 600 | 601 | void wpc_periodic (void) 602 | { 603 | wpc_keypoll (); 604 | 605 | wpc->wdog_timer -= 50; 606 | if (wpc->wdog_timer <= 0) 607 | { 608 | } 609 | 610 | if (wpc->curr_sw_time > 0) 611 | { 612 | wpc->curr_sw_time -= 100; 613 | if (wpc->curr_sw_time <= 0) 614 | { 615 | wpc->curr_sw_time = 0; 616 | wpc_write_switch (wpc->curr_sw, 0); 617 | } 618 | } 619 | } 620 | 621 | void wpc_asic_reset (struct hw_device *dev) 622 | { 623 | memset (wpc, 0, sizeof (struct wpc_asic)); 624 | wpc_write_switch (19, 1); /* Always Closed */ 625 | } 626 | 627 | 628 | struct hw_class wpc_asic_class = 629 | { 630 | .reset = wpc_asic_reset, 631 | .read = wpc_asic_read, 632 | .write = wpc_asic_write, 633 | }; 634 | 635 | struct hw_device *wpc_asic_create (void) 636 | { 637 | if (wpc) 638 | { 639 | fprintf (stderr, "WPC ASIC already created\n"); 640 | return NULL; 641 | } 642 | 643 | wpc = &the_wpc; 644 | return device_attach (&wpc_asic_class, 0x800, wpc); 645 | } 646 | 647 | 648 | void wpc_fault (unsigned int addr, unsigned char type) 649 | { 650 | } 651 | 652 | void wpc_dump_thread (unsigned int thread_id) 653 | { 654 | } 655 | 656 | void io_sym_add (const char *name, unsigned long cpuaddr) 657 | { 658 | sym_add (&program_symtab, name, to_absolute (cpuaddr), 0); 659 | } 660 | 661 | #define IO_SYM_ADD(name) io_sym_add (#name, name) 662 | 663 | 664 | void wpc_init (const char *boot_rom_file) 665 | { 666 | struct hw_device *dev; 667 | int rc; 668 | struct sockaddr_in myaddr; 669 | 670 | device_define ( dev = wpc_asic_create (), 0, 671 | WPC_ASIC_BASE, WPC_PAGED_REGION - WPC_ASIC_BASE, MAP_READWRITE); 672 | 673 | device_define ( dev = ram_create (WPC_RAM_SIZE), 0, 674 | WPC_RAM_BASE, WPC_RAM_SIZE, MAP_READWRITE ); 675 | wpc->ram_dev = dev; 676 | 677 | dev = rom_create (boot_rom_file, WPC_ROM_SIZE); 678 | device_define ( dev, 0, 679 | WPC_PAGED_REGION, WPC_PAGED_SIZE, MAP_READABLE); 680 | device_define ( dev, WPC_ROM_SIZE - WPC_FIXED_SIZE, 681 | WPC_FIXED_REGION, WPC_FIXED_SIZE, MAP_READABLE); 682 | wpc->rom_dev = dev; 683 | 684 | device_define ( dev = ram_create (16 * 512), 0, 685 | 0x3800, 0x200 * 2, MAP_READWRITE ); 686 | wpc->dmd_dev = dev; 687 | 688 | wpc_update_ram (); 689 | 690 | wpc_sock = udp_socket_create (9000); 691 | if (wpc_sock < 0) 692 | fprintf (stderr, "could not open output socket\n"); 693 | 694 | IO_SYM_ADD(WPC_DMD_LOW_BASE); 695 | IO_SYM_ADD(WPC_DMD_HIGH_BASE); 696 | IO_SYM_ADD(WPC_DMD_HIGH_PAGE); 697 | IO_SYM_ADD(WPC_DMD_FIRQ_ROW_VALUE); 698 | IO_SYM_ADD(WPC_DMD_LOW_PAGE); 699 | IO_SYM_ADD(WPC_DMD_ACTIVE_PAGE); 700 | IO_SYM_ADD(WPC_SERIAL_STATUS_PORT); 701 | IO_SYM_ADD(WPC_PARALLEL_DATA_PORT); 702 | IO_SYM_ADD(WPC_PARALLEL_STROBE_PORT); 703 | IO_SYM_ADD(WPC_SERIAL_DATA_OUTPUT); 704 | IO_SYM_ADD(WPC_SERIAL_CONTROL_OUTPUT); 705 | IO_SYM_ADD(WPC_SERIAL_BAUD_SELECT); 706 | IO_SYM_ADD(WPC_TICKET_DISPENSE); 707 | IO_SYM_ADD(WPC_DCS_SOUND_DATA_OUT); 708 | IO_SYM_ADD(WPC_DCS_SOUND_DATA_IN); 709 | IO_SYM_ADD(WPC_DCS_SOUND_RESET); 710 | IO_SYM_ADD(WPC_DCS_SOUND_DATA_READY); 711 | IO_SYM_ADD(WPC_FLIPTRONIC_PORT_A); 712 | IO_SYM_ADD(WPC_FLIPTRONIC_PORT_B); 713 | IO_SYM_ADD(WPCS_DATA); 714 | IO_SYM_ADD(WPCS_CONTROL_STATUS); 715 | IO_SYM_ADD(WPC_SOL_FLASH2_OUTPUT); 716 | IO_SYM_ADD(WPC_SOL_HIGHPOWER_OUTPUT); 717 | IO_SYM_ADD(WPC_SOL_FLASH1_OUTPUT); 718 | IO_SYM_ADD(WPC_SOL_LOWPOWER_OUTPUT); 719 | IO_SYM_ADD(WPC_LAMP_ROW_OUTPUT); 720 | IO_SYM_ADD(WPC_LAMP_COL_STROBE); 721 | IO_SYM_ADD(WPC_GI_TRIAC); 722 | IO_SYM_ADD(WPC_SW_JUMPER_INPUT); 723 | IO_SYM_ADD(WPC_SW_CABINET_INPUT); 724 | IO_SYM_ADD(WPC_SW_ROW_INPUT); 725 | IO_SYM_ADD(WPC_SW_COL_STROBE); 726 | IO_SYM_ADD(WPC_LEDS); 727 | IO_SYM_ADD(WPC_RAM_BANK); 728 | IO_SYM_ADD(WPC_SHIFTADDR); 729 | IO_SYM_ADD(WPC_SHIFTBIT); 730 | IO_SYM_ADD(WPC_SHIFTBIT2); 731 | IO_SYM_ADD(WPC_PERIPHERAL_TIMER_FIRQ_CLEAR); 732 | IO_SYM_ADD(WPC_ROM_LOCK); 733 | IO_SYM_ADD(WPC_CLK_HOURS_DAYS); 734 | IO_SYM_ADD(WPC_CLK_MINS); 735 | IO_SYM_ADD(WPC_ROM_BANK); 736 | IO_SYM_ADD(WPC_RAM_LOCK); 737 | IO_SYM_ADD(WPC_RAM_LOCKSIZE); 738 | } 739 | 740 | 741 | struct machine wpc_machine = 742 | { 743 | .name = "wpc", 744 | .fault = wpc_fault, 745 | .init = wpc_init, 746 | .dump_thread = wpc_dump_thread, 747 | .periodic = wpc_periodic, 748 | }; 749 | 750 | 751 | struct machine wpc95_machine = 752 | { 753 | .name = "wpc95", 754 | .fault = wpc_fault, 755 | .init = wpc_init, 756 | .dump_thread = wpc_dump_thread, 757 | .periodic = wpc_periodic, 758 | }; 759 | 760 | -------------------------------------------------------------------------------- /wpclib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "wpclib.h" 11 | 12 | #define UDP_PORT 7400 13 | 14 | #define CLIENT_PORT_OFFSET 0 15 | #define SERVER_PORT_OFFSET 1 16 | 17 | int client_port = UDP_PORT + CLIENT_PORT_OFFSET; 18 | int server_port = UDP_PORT + SERVER_PORT_OFFSET; 19 | 20 | void udp_socket_error (void) 21 | { 22 | abort (); 23 | } 24 | 25 | int udp_socket_create (int port) 26 | { 27 | int rc; 28 | int s; 29 | struct sockaddr_in myaddr; 30 | 31 | s = socket (PF_INET, SOCK_DGRAM, 0); 32 | if (s < 0) 33 | { 34 | fprintf (stderr, "could not open socket, errno=%d\n", errno); 35 | udp_socket_error (); 36 | return s; 37 | } 38 | 39 | rc = fcntl (s, F_SETFL, O_NONBLOCK); 40 | if (rc < 0) 41 | { 42 | fprintf (stderr, "could not set nonblocking, errno=%d\n", errno); 43 | udp_socket_error (); 44 | return rc; 45 | } 46 | 47 | myaddr.sin_family = AF_INET; 48 | myaddr.sin_port = htons (port); 49 | myaddr.sin_addr.s_addr = INADDR_ANY; 50 | rc = bind (s, (struct sockaddr *)&myaddr, sizeof (myaddr)); 51 | if (rc < 0) 52 | { 53 | fprintf (stderr, "could not bind socket, errno=%d\n", errno); 54 | udp_socket_error (); 55 | return rc; 56 | } 57 | 58 | return s; 59 | } 60 | 61 | int udp_socket_send (int s, int dstport, const void *data, int len) 62 | { 63 | int rc; 64 | struct sockaddr_in to; 65 | 66 | to.sin_family = AF_INET; 67 | to.sin_port = htons (dstport); 68 | to.sin_addr.s_addr = inet_addr ("127.0.0.1"); 69 | rc = sendto (s, data, len, 0, (struct sockaddr *)&to, sizeof (to)); 70 | if ((rc < 0) && (errno != EAGAIN)) 71 | { 72 | fprintf (stderr, "could not send, errno=%d\n", errno); 73 | udp_socket_error (); 74 | } 75 | return rc; 76 | } 77 | 78 | int udp_socket_receive (int s, int dstport, void *data, int len) 79 | { 80 | int rc; 81 | struct sockaddr_in from; 82 | int fromlen; 83 | 84 | rc = recvfrom (s, data, len, 0, (struct sockaddr *)&from, &len); 85 | if ((rc < 0) && (errno != EAGAIN)) 86 | { 87 | fprintf (stderr, "could not receive, errno=%d\n", errno); 88 | udp_socket_error (); 89 | } 90 | return rc; 91 | } 92 | 93 | int wpc_msg_init (int code, struct wpc_message *msg) 94 | { 95 | msg->code = code; 96 | msg->timestamp = 0; 97 | msg->len = 0; 98 | return 0; 99 | } 100 | 101 | int wpc_msg_insert (struct wpc_message *msg, const void *p, int len) 102 | { 103 | memcpy (msg->u.data + msg->len, p, len); 104 | msg->len += len; 105 | } 106 | 107 | int wpc_msg_send (int s, int dstport, struct wpc_message *msg) 108 | { 109 | int rc = udp_socket_send (s, dstport, msg, msg->len + sizeof (struct wpc_message) - 1000); 110 | if (rc < 0) 111 | { 112 | fprintf (stderr, "error: could not send!\n"); 113 | } 114 | return rc; 115 | } 116 | 117 | int udp_socket_close (int s) 118 | { 119 | close (s); 120 | return 0; 121 | } 122 | 123 | 124 | #ifdef STANDALONE 125 | int main (int argc, char *argv[]) 126 | { 127 | int server, client; 128 | char sendbuf[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 129 | char recvbuf[8]; 130 | 131 | server = udp_socket_create (server_port); 132 | client = udp_socket_create (client_port); 133 | printf ("Server = %d, Client = %d\n", server, client); 134 | 135 | getchar (); 136 | printf ("Sending data\n"); 137 | udp_socket_send (client, server_port, sendbuf, sizeof (sendbuf)); 138 | printf ("Receiving data\n"); 139 | udp_socket_receive (server, client_port, recvbuf, sizeof (recvbuf)); 140 | 141 | if (memcmp (sendbuf, recvbuf, sizeof (sendbuf))) 142 | { 143 | printf ("Buffers differ.\n"); 144 | } 145 | 146 | udp_socket_close (server); 147 | udp_socket_close (client); 148 | } 149 | #endif 150 | -------------------------------------------------------------------------------- /wpclib.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _WPCLIB_H 3 | #define _WPCLIB_H 4 | 5 | int udp_socket_create (int port); 6 | int udp_socket_send (int s, int dstport, const void *data, int len); 7 | int udp_socket_receive (int s, int dstport, void *data, int len); 8 | int udp_socket_close (int s); 9 | 10 | #define NUM_DMD_PHASES 3 11 | 12 | struct wpc_message 13 | { 14 | unsigned char code; 15 | unsigned int timestamp; 16 | unsigned int len; 17 | union { 18 | unsigned char data[1600]; 19 | struct _dmdpage_info 20 | { 21 | struct 22 | { 23 | unsigned int page; 24 | unsigned char data[512]; 25 | } phases[NUM_DMD_PHASES]; 26 | } dmdpage; 27 | 28 | struct _dmdvisible_info 29 | { 30 | unsigned int phases[NUM_DMD_PHASES]; 31 | } dmdvisible; 32 | } u; 33 | }; 34 | 35 | int wpc_msg_init (int code, struct wpc_message *msg); 36 | int wpc_msg_insert (struct wpc_message *msg, const void *p, int len); 37 | int wpc_msg_send (int s, int dstport, struct wpc_message *msg); 38 | 39 | #define CODE_DMD_PAGE 0 40 | #define CODE_LAMPS 1 41 | #define CODE_SWITCHES 2 42 | #define CODE_DMD_VISIBLE 3 43 | #define CODE_COILS 4 44 | #define CODE_GEN_ILLUMS 5 45 | 46 | #endif 47 | --------------------------------------------------------------------------------