├── .gdbinit ├── .gitignore ├── COPYING ├── ChangeLog ├── Makefile.in ├── boot.exb ├── bpf.patch ├── config.guess ├── config.h.in ├── config.sub ├── configure ├── configure.in ├── console.c ├── eacalc.c ├── ether_bpf.c ├── ether_dummy.c ├── ether_netbsd.c ├── ether_snit.c ├── ether_ultrix.c ├── exec.exe ├── genboole ├── gendisp ├── genhw ├── genskipjump ├── gentxxx ├── i_arith.c ├── i_byte.c ├── i_io.c ├── i_misc.c ├── i_rh20.c ├── i_shift.c ├── i_simple.c ├── i_skipjump.c ├── i_stack.c ├── install-sh ├── interrupt.c ├── kx10.c ├── loadexe.c ├── misc.c ├── monitr.exe ├── pager.c ├── pdp10.h ├── readconfig.c ├── unpack.c └── version.c /.gdbinit: -------------------------------------------------------------------------------- 1 | b genunimp 2 | b suspend 3 | handle SIGUSR1 pass nostop noprint 4 | define da 5 | handle SIGALRM ign 6 | handle SIGUSR1 ign 7 | handle SIGIO ign 8 | end 9 | 10 | define ea 11 | handle SIGALRM pass 12 | handle SIGUSR1 pass nostop noprint 13 | handle SIGIO pass nostop noprint 14 | end 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.o 3 | kx10 4 | Makefile 5 | config.cache 6 | config.h 7 | config.log 8 | config.status 9 | dispatch.c 10 | i_boole.c 11 | i_hword.c 12 | i_skippy.c 13 | i_txxx.c 14 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 675 Mass Ave, Cambridge, MA 02139, 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 | Appendix: 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) 19yy 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., 675 Mass Ave, Cambridge, MA 02139, USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) 19yy name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Library General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for kx10, the PDP-10 emulator. 3 | # Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 Stu Grossman 4 | # 5 | # This file is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 18 | # 19 | 20 | SHELL= /bin/sh 21 | 22 | SRCDIR=@srcdir@ 23 | 24 | # Optional flags: 25 | # -DPCHIST - Turns on PC history buffer 26 | # -DKLDCP - Make ^E console command start KLDDT at loc 10000 27 | # -DDISK_PROFILE - Generate stats on disk reads and write 28 | # -DPC_PROFILE - Generate stats on PC vm page cache 29 | 30 | CFLAGS=@CFLAGS@ -I. 31 | 32 | LIBS=@LIBS@ 33 | 34 | LDFLAGS=@LDFLAGS@ 35 | 36 | CC=@CC@ 37 | 38 | ETHER_OBJS=@ETHER_OBJS@ 39 | 40 | .c.o: 41 | $(CC) $(CFLAGS) -I$(SRCDIR) -c $< 42 | 43 | INSTRS= $(SRCDIR)/i_misc.c $(SRCDIR)/i_arith.c $(SRCDIR)/i_byte.c $(SRCDIR)/i_io.c $(SRCDIR)/i_rh20.c $(SRCDIR)/i_shift.c $(SRCDIR)/i_simple.c $(SRCDIR)/i_skipjump.c $(SRCDIR)/i_stack.c $(GEN_INSTRS) 44 | GEN_INSTRS= i_boole.c i_hword.c i_txxx.c i_skippy.c 45 | GENERATOR_SCRIPTS= $(SRCDIR)/gendisp $(SRCDIR)/genboole $(SRCDIR)/genhw $(SRCDIR)/gentxxx $(SRCDIR)/genskipjump 46 | GEN_SRCS= dispatch.c $(GEN_INSTRS) 47 | INSTR_OBJS= i_arith.o i_boole.o i_byte.o i_hword.o i_io.o i_misc.o i_rh20.o i_shift.o i_simple.o i_skipjump.o i_skippy.o i_stack.o i_txxx.o 48 | OBJS= kx10.o loadexe.o pager.o eacalc.o $(INSTR_OBJS) console.o interrupt.o dispatch.o misc.o version.o $(ETHER_OBJS) readconfig.o 49 | ALL_OBJS=$(OBJS) ether_bpf.o ether_dummy.o ether_netbsd.o ether_snit.o 50 | 51 | kx10: $(OBJS) 52 | $(CC) $(CFLAGS) $(LDFLAGS) -o kx10 $(OBJS) $(LIBS) 53 | 54 | dispatch.c: $(INSTRS) $(SRCDIR)/gendisp 55 | perl $(SRCDIR)/gendisp $(INSTRS) 56 | 57 | i_boole.c: $(SRCDIR)/genboole 58 | perl $(SRCDIR)/genboole > i_boole.c 59 | 60 | i_hword.c: $(SRCDIR)/genhw 61 | perl $(SRCDIR)/genhw > i_hword.c 62 | 63 | i_txxx.c: $(SRCDIR)/gentxxx 64 | perl $(SRCDIR)/gentxxx > i_txxx.c 65 | 66 | i_skippy.c: $(SRCDIR)/genskipjump 67 | perl $(SRCDIR)/genskipjump > i_skippy.c 68 | 69 | # Only needed for Alpha/OSF-1* 70 | pfopen.o: /usr/examples/packetfilter/pfopen.c 71 | $(CC) $(CFLAGS) -c /usr/examples/packetfilter/pfopen.c 72 | 73 | clean: 74 | -rm -f $(ALL_OBJS) kx10 *~ 75 | 76 | veryclean: clean 77 | -rm -f dispatch.c i_txxx.c i_skippy.c i_hword.c i_boole.c 78 | 79 | dist: veryclean $(GENERATOR_SCRIPTS) $(GEN_SRCS) 80 | chmod 644 * 81 | 82 | $(ALL_OBJS): $(SRCDIR)/pdp10.h 83 | 84 | console.o: $(SRCDIR)/console.c 85 | $(CC) $(CFLAGS) -c $(SRCDIR)/console.c 86 | 87 | eacalc.o: $(SRCDIR)/eacalc.c 88 | $(CC) $(CFLAGS) -c $(SRCDIR)/eacalc.c 89 | 90 | ether_bpf.o: $(SRCDIR)/ether_bpf.c 91 | $(CC) $(CFLAGS) -c $(SRCDIR)/ether_bpf.c 92 | 93 | ether_dummy.o: $(SRCDIR)/ether_dummy.c 94 | $(CC) $(CFLAGS) -c $(SRCDIR)/ether_dummy.c 95 | 96 | ether_netbsd.o: $(SRCDIR)/ether_netbsd.c 97 | $(CC) $(CFLAGS) -c $(SRCDIR)/ether_netbsd.c 98 | 99 | ether_snit.o: $(SRCDIR)/ether_snit.c 100 | $(CC) $(CFLAGS) -c $(SRCDIR)/ether_snit.c 101 | 102 | ether_ultrix.o: $(SRCDIR)/ether_ultrix.c 103 | $(CC) $(CFLAGS) -c $(SRCDIR)/ether_ultrix.c 104 | 105 | i_arith.o: $(SRCDIR)/i_arith.c 106 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_arith.c 107 | 108 | i_byte.o: $(SRCDIR)/i_byte.c 109 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_byte.c 110 | 111 | i_io.o: $(SRCDIR)/i_io.c 112 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_io.c 113 | 114 | i_misc.o: $(SRCDIR)/i_misc.c 115 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_misc.c 116 | 117 | i_rh20.o: $(SRCDIR)/i_rh20.c 118 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_rh20.c 119 | 120 | i_shift.o: $(SRCDIR)/i_shift.c 121 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_shift.c 122 | 123 | i_simple.o: $(SRCDIR)/i_simple.c 124 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_simple.c 125 | 126 | i_skipjump.o: $(SRCDIR)/i_skipjump.c 127 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_skipjump.c 128 | 129 | i_stack.o: $(SRCDIR)/i_stack.c 130 | $(CC) $(CFLAGS) -c $(SRCDIR)/i_stack.c 131 | 132 | interrupt.o: $(SRCDIR)/interrupt.c 133 | $(CC) $(CFLAGS) -c $(SRCDIR)/interrupt.c 134 | 135 | kx10.o: $(SRCDIR)/kx10.c 136 | $(CC) $(CFLAGS) -c $(SRCDIR)/kx10.c 137 | 138 | loadexe.o: $(SRCDIR)/loadexe.c 139 | $(CC) $(CFLAGS) -c $(SRCDIR)/loadexe.c 140 | 141 | misc.o: $(SRCDIR)/misc.c 142 | $(CC) $(CFLAGS) -c $(SRCDIR)/misc.c 143 | 144 | pager.o: $(SRCDIR)/pager.c 145 | $(CC) $(CFLAGS) -c $(SRCDIR)/pager.c 146 | 147 | version.o: $(SRCDIR)/version.c 148 | $(CC) $(CFLAGS) -c $(SRCDIR)/version.c 149 | 150 | readconfig.o: $(SRCDIR)/readconfig.c 151 | $(CC) $(CFLAGS) -c $(SRCDIR)/readconfig.c 152 | -------------------------------------------------------------------------------- /boot.exb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brouhaha/kx10/6f4f55267176727dc3c34ff60a269fe6dab22a7c/boot.exb -------------------------------------------------------------------------------- /bpf.patch: -------------------------------------------------------------------------------- 1 | diff -c orig/bpf.c new/bpf.c 2 | *** orig/bpf.c Fri Jul 15 15:32:27 1994 3 | --- new/bpf.c Sat Jun 10 16:12:14 1995 4 | *************** 5 | *** 325,330 **** 6 | --- 325,331 ---- 7 | /* Mark "free" and do most initialization. */ 8 | bzero((char *)d, sizeof(*d)); 9 | d->bd_bufsize = bpf_bufsize; 10 | + d->bd_sig = SIGIO; 11 | 12 | return (0); 13 | } 14 | *************** 15 | *** 436,443 **** 16 | ROTATE_BUFFERS(d); 17 | break; 18 | } 19 | ! error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf", 20 | ! d->bd_rtout); 21 | if (error == EINTR || error == ERESTART) { 22 | splx(s); 23 | return (error); 24 | --- 437,447 ---- 25 | ROTATE_BUFFERS(d); 26 | break; 27 | } 28 | ! if (d->bd_rtout != -1) 29 | ! error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf", 30 | ! d->bd_rtout); 31 | ! else 32 | ! error = EWOULDBLOCK; /* User requested non-blocking I/O */ 33 | if (error == EINTR || error == ERESTART) { 34 | splx(s); 35 | return (error); 36 | *************** 37 | *** 493,499 **** 38 | --- 497,511 ---- 39 | bpf_wakeup(d) 40 | register struct bpf_d *d; 41 | { 42 | + struct proc *p; 43 | + 44 | wakeup((caddr_t)d); 45 | + if (d->bd_async && d->bd_sig) 46 | + if (d->bd_pgid > 0) 47 | + gsignal (d->bd_pgid, d->bd_sig); 48 | + else if (p = pfind (-d->bd_pgid)) 49 | + psignal (p, d->bd_sig); 50 | + 51 | #if BSD >= 199103 52 | selwakeup(&d->bd_sel); 53 | /* XXX */ 54 | *************** 55 | *** 779,784 **** 56 | --- 791,838 ---- 57 | bv->bv_minor = BPF_MINOR_VERSION; 58 | break; 59 | } 60 | + 61 | + 62 | + case FIONBIO: /* Non-blocking I/O */ 63 | + if (*(int *)addr) 64 | + d->bd_rtout = -1; 65 | + else 66 | + d->bd_rtout = 0; 67 | + break; 68 | + 69 | + case FIOASYNC: /* Send signal on receive packets */ 70 | + d->bd_async = *(int *)addr; 71 | + break; 72 | + 73 | + /* N.B. ioctl (FIOSETOWN) and fcntl (F_SETOWN) both end up doing the 74 | + equivalent of a TIOCSPGRP and hence end up here. *However* TIOCSPGRP's arg 75 | + is a process group if it's positive and a process id if it's negative. This 76 | + is exactly the opposite of what the other two functions want! Therefore 77 | + there is code in ioctl and fcntl to negate the arg before calling here. */ 78 | + 79 | + case TIOCSPGRP: /* Process or group to send signals to */ 80 | + d->bd_pgid = *(int *)addr; 81 | + break; 82 | + 83 | + case TIOCGPGRP: 84 | + *(int *)addr = d->bd_pgid; 85 | + break; 86 | + 87 | + case BIOCSRSIG: /* Set receive signal */ 88 | + { 89 | + u_int sig; 90 | + 91 | + sig = *(u_int *)addr; 92 | + 93 | + if (sig >= NSIG) 94 | + error = EINVAL; 95 | + else 96 | + d->bd_sig = sig; 97 | + break; 98 | + } 99 | + case BIOCGRSIG: 100 | + *(u_int *)addr = d->bd_sig; 101 | + break; 102 | } 103 | return (error); 104 | } 105 | diff -c orig/bpf.h new/bpf.h 106 | *** orig/bpf.h Tue Jun 28 23:35:54 1994 107 | --- new/bpf.h Sat Jun 10 16:12:14 1995 108 | *************** 109 | *** 121,126 **** 110 | --- 121,128 ---- 111 | #define BIOCGSTATS _IOR('B',111, struct bpf_stat) 112 | #define BIOCIMMEDIATE _IOW('B',112, u_int) 113 | #define BIOCVERSION _IOR('B',113, struct bpf_version) 114 | + #define BIOCSRSIG _IOW('B',114, u_int) 115 | + #define BIOCGRSIG _IOR('B',115, u_int) 116 | #endif 117 | 118 | /* 119 | diff -c orig/bpfdesc.h new/bpfdesc.h 120 | *** orig/bpfdesc.h Tue Jun 28 23:35:58 1994 121 | --- new/bpfdesc.h Sat Jun 10 16:12:14 1995 122 | *************** 123 | *** 73,78 **** 124 | --- 73,81 ---- 125 | u_char bd_promisc; /* true if listening promiscuously */ 126 | u_char bd_state; /* idle, waiting, or timed out */ 127 | u_char bd_immediate; /* true to return on packet arrival */ 128 | + int bd_async; /* non-zero if packet reception should generate signal */ 129 | + int bd_sig; /* signal to send upon packet reception */ 130 | + pid_t bd_pgid; /* process or group id for signal */ 131 | #if BSD < 199103 132 | u_char bd_selcoll; /* true if selects collide */ 133 | int bd_timedout; 134 | -------------------------------------------------------------------------------- /config.guess: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Attempt to guess a canonical system name. 3 | # Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 4 | # 5 | # This file is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | # 19 | # As a special exception to the GNU General Public License, if you 20 | # distribute this file as part of a program that contains a 21 | # configuration script generated by Autoconf, you may include it under 22 | # the same distribution terms that you use for the rest of that program. 23 | 24 | # Written by Per Bothner . 25 | # The master version of this file is at the FSF in /home/gd/gnu/lib. 26 | # 27 | # This script attempts to guess a canonical system name similar to 28 | # config.sub. If it succeeds, it prints the system name on stdout, and 29 | # exits with 0. Otherwise, it exits with 1. 30 | # 31 | # The plan is that this can be called by configure scripts if you 32 | # don't specify an explicit system type (host/target name). 33 | # 34 | # Only a few systems have been added to this list; please add others 35 | # (but try to keep the structure clean). 36 | # 37 | 38 | # This is needed to find uname on a Pyramid OSx when run in the BSD universe. 39 | # (ghazi@noc.rutgers.edu 8/24/94.) 40 | if (test -f /.attbin/uname) >/dev/null 2>&1 ; then 41 | PATH=$PATH:/.attbin ; export PATH 42 | fi 43 | 44 | UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown 45 | UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown 46 | UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown 47 | UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown 48 | 49 | trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 50 | 51 | # Note: order is significant - the case branches are not exclusive. 52 | 53 | case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in 54 | alpha:OSF1:V*:*) 55 | # After 1.2, OSF1 uses "V1.3" for uname -r. 56 | echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'` 57 | exit 0 ;; 58 | alpha:OSF1:*:*) 59 | # 1.2 uses "1.2" for uname -r. 60 | echo alpha-dec-osf${UNAME_RELEASE} 61 | exit 0 ;; 62 | 21064:Windows_NT:50:3) 63 | echo alpha-dec-winnt3.5 64 | exit 0 ;; 65 | amiga:NetBSD:*:*) 66 | echo m68k-cbm-netbsd${UNAME_RELEASE} 67 | exit 0 ;; 68 | arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) 69 | echo arm-acorn-riscix${UNAME_RELEASE} 70 | exit 0;; 71 | Pyramid*:OSx*:*:*) 72 | if test "`(/bin/universe) 2>/dev/null`" = att ; then 73 | echo pyramid-pyramid-sysv3 74 | else 75 | echo pyramid-pyramid-bsd 76 | fi 77 | exit 0 ;; 78 | sun4*:SunOS:5.*:*) 79 | echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` 80 | exit 0 ;; 81 | i86pc:SunOS:5.*:*) 82 | echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` 83 | exit 0 ;; 84 | sun4*:SunOS:6*:*) 85 | # According to config.sub, this is the proper way to canonicalize 86 | # SunOS6. Hard to guess exactly what SunOS6 will be like, but 87 | # it's likely to be more like Solaris than SunOS4. 88 | echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` 89 | exit 0 ;; 90 | sun4*:SunOS:*:*) 91 | case "`/usr/bin/arch -k`" in 92 | Series*|S4*) 93 | UNAME_RELEASE=`uname -v` 94 | ;; 95 | esac 96 | # Japanese Language versions have a version number like `4.1.3-JL'. 97 | echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` 98 | exit 0 ;; 99 | sun3*:SunOS:*:*) 100 | echo m68k-sun-sunos${UNAME_RELEASE} 101 | exit 0 ;; 102 | atari*:NetBSD:*:*) 103 | echo m68k-atari-netbsd${UNAME_RELEASE} 104 | exit 0 ;; 105 | sun3*:NetBSD:*:*) 106 | echo m68k-sun-netbsd${UNAME_RELEASE} 107 | exit 0 ;; 108 | mac68k:NetBSD:*:*) 109 | echo m68k-apple-netbsd${UNAME_RELEASE} 110 | exit 0 ;; 111 | RISC*:ULTRIX:*:*) 112 | echo mips-dec-ultrix${UNAME_RELEASE} 113 | exit 0 ;; 114 | VAX*:ULTRIX*:*:*) 115 | echo vax-dec-ultrix${UNAME_RELEASE} 116 | exit 0 ;; 117 | mips:*:5*:RISCos) 118 | echo mips-mips-riscos${UNAME_RELEASE} 119 | exit 0 ;; 120 | m88k:CX/UX:7*:*) 121 | echo m88k-harris-cxux7 122 | exit 0 ;; 123 | m88k:*:4*:R4*) 124 | echo m88k-motorola-sysv4 125 | exit 0 ;; 126 | m88k:*:3*:R3*) 127 | echo m88k-motorola-sysv3 128 | exit 0 ;; 129 | AViiON:dgux:*:*) 130 | if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ 131 | -o ${TARGET_BINARY_INTERFACE}x = x ] ; then 132 | echo m88k-dg-dgux${UNAME_RELEASE} 133 | else 134 | echo m88k-dg-dguxbcs${UNAME_RELEASE} 135 | fi 136 | exit 0 ;; 137 | M88*:DolphinOS:*:*) # DolphinOS (SVR3) 138 | echo m88k-dolphin-sysv3 139 | exit 0 ;; 140 | M88*:*:R3*:*) 141 | # Delta 88k system running SVR3 142 | echo m88k-motorola-sysv3 143 | exit 0 ;; 144 | XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) 145 | echo m88k-tektronix-sysv3 146 | exit 0 ;; 147 | Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) 148 | echo m68k-tektronix-bsd 149 | exit 0 ;; 150 | *:IRIX*:*:*) 151 | echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` 152 | exit 0 ;; 153 | ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. 154 | echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id 155 | exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' 156 | i[34]86:AIX:*:*) 157 | echo i386-ibm-aix 158 | exit 0 ;; 159 | *:AIX:2:3) 160 | if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then 161 | sed 's/^ //' << EOF >dummy.c 162 | #include 163 | 164 | main() 165 | { 166 | if (!__power_pc()) 167 | exit(1); 168 | puts("powerpc-ibm-aix3.2.5"); 169 | exit(0); 170 | } 171 | EOF 172 | ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 173 | rm -f dummy.c dummy 174 | echo rs6000-ibm-aix3.2.5 175 | elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then 176 | echo rs6000-ibm-aix3.2.4 177 | else 178 | echo rs6000-ibm-aix3.2 179 | fi 180 | exit 0 ;; 181 | *:AIX:*:4) 182 | if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then 183 | IBM_ARCH=rs6000 184 | else 185 | IBM_ARCH=powerpc 186 | fi 187 | if grep bos410 /usr/include/stdio.h >/dev/null 2>&1; then 188 | IBM_REV=4.1 189 | elif grep bos411 /usr/include/stdio.h >/dev/null 2>&1; then 190 | IBM_REV=4.1.1 191 | else 192 | IBM_REV=4.${UNAME_RELEASE} 193 | fi 194 | echo ${IBM_ARCH}-ibm-aix${IBM_REV} 195 | exit 0 ;; 196 | *:AIX:*:*) 197 | echo rs6000-ibm-aix 198 | exit 0 ;; 199 | ibmrt:4.4BSD:*|romp-ibm:BSD:*) 200 | echo romp-ibm-bsd4.4 201 | exit 0 ;; 202 | ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and 203 | echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to 204 | exit 0 ;; # report: romp-ibm BSD 4.3 205 | *:BOSX:*:*) 206 | echo rs6000-bull-bosx 207 | exit 0 ;; 208 | DPX/2?00:B.O.S.:*:*) 209 | echo m68k-bull-sysv3 210 | exit 0 ;; 211 | 9000/[34]??:4.3bsd:1.*:*) 212 | echo m68k-hp-bsd 213 | exit 0 ;; 214 | hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) 215 | echo m68k-hp-bsd4.4 216 | exit 0 ;; 217 | 9000/[3478]??:HP-UX:*:*) 218 | case "${UNAME_MACHINE}" in 219 | 9000/31? ) HP_ARCH=m68000 ;; 220 | 9000/[34]?? ) HP_ARCH=m68k ;; 221 | 9000/7?? | 9000/8?7 ) HP_ARCH=hppa1.1 ;; 222 | 9000/8?? ) HP_ARCH=hppa1.0 ;; 223 | esac 224 | HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` 225 | echo ${HP_ARCH}-hp-hpux${HPUX_REV} 226 | exit 0 ;; 227 | 3050*:HI-UX:*:*) 228 | sed 's/^ //' << EOF >dummy.c 229 | #include 230 | int 231 | main () 232 | { 233 | long cpu = sysconf (_SC_CPU_VERSION); 234 | /* The order matters, because CPU_IS_HP_MC68K erroneously returns 235 | true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct 236 | results, however. */ 237 | if (CPU_IS_PA_RISC (cpu)) 238 | { 239 | switch (cpu) 240 | { 241 | case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; 242 | case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; 243 | case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; 244 | default: puts ("hppa-hitachi-hiuxwe2"); break; 245 | } 246 | } 247 | else if (CPU_IS_HP_MC68K (cpu)) 248 | puts ("m68k-hitachi-hiuxwe2"); 249 | else puts ("unknown-hitachi-hiuxwe2"); 250 | exit (0); 251 | } 252 | EOF 253 | ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 254 | rm -f dummy.c dummy 255 | echo unknown-hitachi-hiuxwe2 256 | exit 0 ;; 257 | 9000/7??:4.3bsd:*:* | 9000/8?7:4.3bsd:*:* ) 258 | echo hppa1.1-hp-bsd 259 | exit 0 ;; 260 | 9000/8??:4.3bsd:*:*) 261 | echo hppa1.0-hp-bsd 262 | exit 0 ;; 263 | hp7??:OSF1:*:* | hp8?7:OSF1:*:* ) 264 | echo hppa1.1-hp-osf 265 | exit 0 ;; 266 | hp8??:OSF1:*:*) 267 | echo hppa1.0-hp-osf 268 | exit 0 ;; 269 | parisc*:Lites*:*:*) 270 | echo hppa1.1-hp-lites 271 | exit 0 ;; 272 | C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) 273 | echo c1-convex-bsd 274 | exit 0 ;; 275 | C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) 276 | if getsysinfo -f scalar_acc 277 | then echo c32-convex-bsd 278 | else echo c2-convex-bsd 279 | fi 280 | exit 0 ;; 281 | C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) 282 | echo c34-convex-bsd 283 | exit 0 ;; 284 | C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) 285 | echo c38-convex-bsd 286 | exit 0 ;; 287 | C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) 288 | echo c4-convex-bsd 289 | exit 0 ;; 290 | CRAY*X-MP:*:*:*) 291 | echo xmp-cray-unicos 292 | exit 0 ;; 293 | CRAY*Y-MP:*:*:*) 294 | echo ymp-cray-unicos${UNAME_RELEASE} 295 | exit 0 ;; 296 | CRAY*C90:*:*:*) 297 | echo c90-cray-unicos${UNAME_RELEASE} 298 | exit 0 ;; 299 | CRAY-2:*:*:*) 300 | echo cray2-cray-unicos 301 | exit 0 ;; 302 | hp3[0-9][05]:NetBSD:*:*) 303 | echo m68k-hp-netbsd${UNAME_RELEASE} 304 | exit 0 ;; 305 | i[34]86:BSD/386:*:* | *:BSD/OS:*:*) 306 | echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} 307 | exit 0 ;; 308 | *:FreeBSD:*:*) 309 | echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` 310 | exit 0 ;; 311 | *:NetBSD:*:*) 312 | echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` 313 | exit 0 ;; 314 | *:GNU:*:*) 315 | echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` 316 | exit 0 ;; 317 | *:Linux:*:*) 318 | # Systems without a BFD linker 319 | if test -d /usr/lib/ldscripts/. ; then 320 | : 321 | else 322 | echo "${UNAME_MACHINE}-unknown-linuxoldld" 323 | exit 0 324 | fi 325 | # Determine whether the default compiler is a.out or elf 326 | cat >dummy.c </dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 340 | rm -f dummy.c dummy;; 341 | # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions 342 | # are messed up and put the nodename in both sysname and nodename. 343 | i[34]86:DYNIX/ptx:4*:*) 344 | echo i386-sequent-sysv4 345 | exit 0 ;; 346 | i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*) 347 | if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then 348 | echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} 349 | else 350 | echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE} 351 | fi 352 | exit 0 ;; 353 | i[34]86:*:3.2:*) 354 | if test -f /usr/options/cb.name; then 355 | UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then 358 | UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` 359 | (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 360 | echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL 361 | else 362 | echo ${UNAME_MACHINE}-unknown-sysv32 363 | fi 364 | exit 0 ;; 365 | Intel:Mach:3*:*) 366 | echo i386-unknown-mach3 367 | exit 0 ;; 368 | paragon:*:*:*) 369 | echo i860-intel-osf1 370 | exit 0 ;; 371 | i860:*:4.*:*) # i860-SVR4 372 | if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then 373 | echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 374 | else # Add other i860-SVR4 vendors below as they are discovered. 375 | echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 376 | fi 377 | exit 0 ;; 378 | mini*:CTIX:SYS*5:*) 379 | # "miniframe" 380 | echo m68010-convergent-sysv 381 | exit 0 ;; 382 | M680[234]0:*:R3V[567]*:*) 383 | test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 384 | 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0) 385 | uname -p 2>/dev/null | grep 86 >/dev/null \ 386 | && echo i486-ncr-sysv4.3 && exit 0 ;; 387 | 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) 388 | uname -p 2>/dev/null | grep 86 >/dev/null \ 389 | && echo i486-ncr-sysv4 && exit 0 ;; 390 | m680[234]0:LynxOS:2.2*:*) 391 | echo m68k-lynx-lynxos${UNAME_RELEASE} 392 | exit 0 ;; 393 | mc68030:UNIX_System_V:4.*:*) 394 | echo m68k-atari-sysv4 395 | exit 0 ;; 396 | i[34]86:LynxOS:2.2*:*) 397 | echo i386-lynx-lynxos${UNAME_RELEASE} 398 | exit 0 ;; 399 | TSUNAMI:LynxOS:2.2*:*) 400 | echo sparc-lynx-lynxos${UNAME_RELEASE} 401 | exit 0 ;; 402 | rs6000:LynxOS:2.2*:*) 403 | echo rs6000-lynx-lynxos${UNAME_RELEASE} 404 | exit 0 ;; 405 | RM*:SINIX-*:*:*) 406 | echo mips-sni-sysv4 407 | exit 0 ;; 408 | *:SINIX-*:*:*) 409 | if uname -p 2>/dev/null >/dev/null ; then 410 | UNAME_MACHINE=`(uname -p) 2>/dev/null` 411 | echo ${UNAME_MACHINE}-sni-sysv4 412 | else 413 | echo ns32k-sni-sysv 414 | fi 415 | exit 0 ;; 416 | esac 417 | 418 | #echo '(No uname command or uname output not recognized.)' 1>&2 419 | #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 420 | 421 | cat >dummy.c < 431 | printf ("m68k-sony-newsos%s\n", 432 | #ifdef NEWSOS4 433 | "4" 434 | #else 435 | "" 436 | #endif 437 | ); exit (0); 438 | #endif 439 | #endif 440 | 441 | #if defined (__arm) && defined (__acorn) && defined (__unix) 442 | printf ("arm-acorn-riscix"); exit (0); 443 | #endif 444 | 445 | #if defined (hp300) && !defined (hpux) 446 | printf ("m68k-hp-bsd\n"); exit (0); 447 | #endif 448 | 449 | #if defined (NeXT) 450 | #if !defined (__ARCHITECTURE__) 451 | #define __ARCHITECTURE__ "m68k" 452 | #endif 453 | int version; 454 | version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; 455 | printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3"); 456 | exit (0); 457 | #endif 458 | 459 | #if defined (MULTIMAX) || defined (n16) 460 | #if defined (UMAXV) 461 | printf ("ns32k-encore-sysv\n"); exit (0); 462 | #else 463 | #if defined (CMU) 464 | printf ("ns32k-encore-mach\n"); exit (0); 465 | #else 466 | printf ("ns32k-encore-bsd\n"); exit (0); 467 | #endif 468 | #endif 469 | #endif 470 | 471 | #if defined (__386BSD__) 472 | printf ("i386-unknown-bsd\n"); exit (0); 473 | #endif 474 | 475 | #if defined (sequent) 476 | #if defined (i386) 477 | printf ("i386-sequent-dynix\n"); exit (0); 478 | #endif 479 | #if defined (ns32000) 480 | printf ("ns32k-sequent-dynix\n"); exit (0); 481 | #endif 482 | #endif 483 | 484 | #if defined (_SEQUENT_) 485 | printf ("i386-sequent-ptx\n"); exit (0); 486 | #endif 487 | 488 | #if defined (vax) 489 | #if !defined (ultrix) 490 | printf ("vax-dec-bsd\n"); exit (0); 491 | #else 492 | printf ("vax-dec-ultrix\n"); exit (0); 493 | #endif 494 | #endif 495 | 496 | #if defined (alliant) && defined (i860) 497 | printf ("i860-alliant-bsd\n"); exit (0); 498 | #endif 499 | 500 | exit (1); 501 | } 502 | EOF 503 | 504 | ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 505 | rm -f dummy.c dummy 506 | 507 | # Apollos put the system type in the environment. 508 | 509 | test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } 510 | 511 | # Convex versions that predate uname can use getsysinfo(1) 512 | 513 | if [ -x /usr/convex/getsysinfo ] 514 | then 515 | case `getsysinfo -f cpu_type` in 516 | c1*) 517 | echo c1-convex-bsd 518 | exit 0 ;; 519 | c2*) 520 | if getsysinfo -f scalar_acc 521 | then echo c32-convex-bsd 522 | else echo c2-convex-bsd 523 | fi 524 | exit 0 ;; 525 | c34*) 526 | echo c34-convex-bsd 527 | exit 0 ;; 528 | c38*) 529 | echo c38-convex-bsd 530 | exit 0 ;; 531 | c4*) 532 | echo c4-convex-bsd 533 | exit 0 ;; 534 | esac 535 | fi 536 | 537 | #echo '(Unable to guess system type)' 1>&2 538 | 539 | exit 1 540 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated automatically from configure.in by autoheader. */ 2 | 3 | /* Define if using alloca.c. */ 4 | #undef C_ALLOCA 5 | 6 | /* Define to empty if the keyword does not work. */ 7 | #undef const 8 | 9 | /* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. 10 | This function is required for alloca.c support on those systems. */ 11 | #undef CRAY_STACKSEG_END 12 | 13 | /* Define if you have alloca, as a function or macro. */ 14 | #undef HAVE_ALLOCA 15 | 16 | /* Define if you have and it should be used (not on Ultrix). */ 17 | #undef HAVE_ALLOCA_H 18 | 19 | /* Define to `long' if doesn't define. */ 20 | #undef off_t 21 | 22 | /* Define as the return type of signal handlers (int or void). */ 23 | #undef RETSIGTYPE 24 | 25 | /* Define to `unsigned' if doesn't define. */ 26 | #undef size_t 27 | 28 | /* If using the C implementation of alloca, define if you know the 29 | direction of stack growth for your system; otherwise it will be 30 | automatically deduced at run-time. 31 | STACK_DIRECTION > 0 => grows toward higher addresses 32 | STACK_DIRECTION < 0 => grows toward lower addresses 33 | STACK_DIRECTION = 0 => direction of growth unknown 34 | */ 35 | #undef STACK_DIRECTION 36 | 37 | /* Define if you have the ANSI C header files. */ 38 | #undef STDC_HEADERS 39 | 40 | /* Define if you can safely include both and . */ 41 | #undef TIME_WITH_SYS_TIME 42 | 43 | /* Define if your declares struct tm. */ 44 | #undef TM_IN_SYS_TIME 45 | 46 | /* Define if you have the gettimeofday function. */ 47 | #undef HAVE_GETTIMEOFDAY 48 | 49 | /* Define if you have the select function. */ 50 | #undef HAVE_SELECT 51 | 52 | /* Define if you have the socket function. */ 53 | #undef HAVE_SOCKET 54 | 55 | /* Define if you have the strtol function. */ 56 | #undef HAVE_STRTOL 57 | 58 | /* Define if you have the header file. */ 59 | #undef HAVE_FCNTL_H 60 | 61 | /* Define if you have the header file. */ 62 | #undef HAVE_SGTTY_H 63 | 64 | /* Define if you have the header file. */ 65 | #undef HAVE_SYS_FILE_H 66 | 67 | /* Define if you have the header file. */ 68 | #undef HAVE_SYS_IOCTL_H 69 | 70 | /* Define if you have the header file. */ 71 | #undef HAVE_SYS_TIME_H 72 | 73 | /* Define if you have the header file. */ 74 | #undef HAVE_TERMIO_H 75 | 76 | /* Define if you have the header file. */ 77 | #undef HAVE_UNISTD_H 78 | 79 | /* Define as __inline if that's what the C compiler calls it. */ 80 | #undef inline 81 | 82 | /* Define these for Irix to make signals and console I/O work right. */ 83 | #undef USE_STREAMS 84 | #undef _BSD_COMPAT 85 | 86 | #ifdef __GNUC__ 87 | #define NORETURN __attribute__ ((noreturn)) 88 | #else 89 | #define NORETURN 90 | #endif 91 | 92 | #ifdef __STDC__ 93 | #define PARAMS(ARGS) ARGS 94 | #else 95 | #define PARAMS(ARGS) () 96 | #define volatile 97 | #define const 98 | #define signed 99 | #endif 100 | 101 | #ifdef __STDC__ 102 | 103 | #define CONCAT(A, B) A ## B 104 | #define CONCAT4(A, B, C, D) A ## B ## C ## D 105 | 106 | #else /* not __STDC__ */ 107 | 108 | #define CONCAT(A, B) A/**/B 109 | #define CONCAT4(A, B, C, D) A/**/B/**/C/**/D 110 | 111 | #endif 112 | 113 | -------------------------------------------------------------------------------- /configure.in: -------------------------------------------------------------------------------- 1 | dnl Process this file with autoconf to produce a configure script. 2 | AC_INIT(pdp10.h) 3 | 4 | AC_CONFIG_HEADER(config.h) 5 | 6 | AC_CANONICAL_HOST 7 | 8 | dnl Checks for programs. 9 | AC_PROG_CC 10 | 11 | dnl Checks for libraries. 12 | 13 | dnl Checks for header files. 14 | AC_HEADER_STDC 15 | AC_CHECK_HEADERS(fcntl.h sgtty.h sys/file.h sys/ioctl.h sys/time.h termio.h unistd.h) 16 | 17 | dnl Set system dependent compiler options 18 | 19 | case ${CC}X${host_os}X${host_cpu} in 20 | ccXirix*) 21 | CFLAGS="-O -woff 848 -common" 22 | ;; 23 | gccXultrix4*) 24 | CFLAGS="-O -g" 25 | LIBS="-lresolv -l44bsd" 26 | ;; 27 | gccX*[[345]]86*) 28 | CFLAGS="-O -m486 -fomit-frame-pointer -g" 29 | ;; 30 | cc*) 31 | CFLAGS=-O 32 | ;; 33 | esac 34 | 35 | dnl System dependent options 36 | 37 | ETHER_OBJS=ether_dummy.o 38 | 39 | case ${host_os} in 40 | irix*) 41 | AC_DEFINE(USE_STREAMS) 42 | AC_DEFINE(_BSD_COMPAT) 43 | ;; 44 | netbsd* | bsdi* | freebsd*) 45 | ETHER_OBJS=ether_netbsd.o 46 | ;; 47 | osf*) 48 | ETHER_OBJS=ether_bpf.o 49 | AC_CHECK_LIB(c, pfopen,,[ETHER_OBS=${ETHER_OBS} pfopen.o]) 50 | ;; 51 | sunos*) 52 | ETHER_OBJS=ether_snit.o 53 | ;; 54 | solaris*) 55 | AC_DEFINE(USE_STREAMS) 56 | ;; 57 | ultrix4*) 58 | ETHER_OBJS=ether_ultrix.o 59 | ;; 60 | sysv4*) 61 | AC_DEFINE(USE_STREAMS) 62 | ;; 63 | esac 64 | 65 | AC_SUBST(ETHER_OBJS) 66 | 67 | dnl Checks for typedefs, structures, and compiler characteristics. 68 | AC_C_CONST 69 | AC_C_INLINE 70 | AC_TYPE_OFF_T 71 | AC_TYPE_SIZE_T 72 | AC_HEADER_TIME 73 | AC_STRUCT_TM 74 | 75 | dnl Checks for library functions. 76 | AC_FUNC_ALLOCA 77 | AC_PROG_GCC_TRADITIONAL 78 | AC_FUNC_MEMCMP 79 | AC_TYPE_SIGNAL 80 | AC_CHECK_FUNCS(gettimeofday select socket strtol) 81 | 82 | AC_OUTPUT(Makefile) 83 | -------------------------------------------------------------------------------- /console.c: -------------------------------------------------------------------------------- 1 | /* Console I/O routines for kx10, the PDP-10 emulator. 2 | Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 3 | Stu Grossman 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 18 | 19 | #include "pdp10.h" 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef USE_STREAMS 29 | #include 30 | #endif 31 | 32 | extern int errno; 33 | static void alarm_handler(); 34 | 35 | static volatile char consbuf[400]; /* Console input buffer */ 36 | static volatile char *consiptr = consbuf; /* Next place to put a newly arrived char */ 37 | static volatile char *consoptr = consbuf; /* Next place to get the oldest char */ 38 | static struct termios otermios; /* Saved tty variables */ 39 | static int oflags; 40 | 41 | static int console_fd = -1; 42 | 43 | /* The type of protocol to simulate when talking with the -10 program. primary 44 | is a shared-memory protocol used under timesharing mostly for communicating 45 | with front-end ttys. secondary is a much simpler semaphore-based protocol 46 | which is used during booting and debugging (EDDT). kldcp is very similar to 47 | secondary, but doesn't use the DTE doorbell mechanism. The -10 is expected 48 | to poll for typein. It is used only by KLDCP and WAITS. */ 49 | 50 | enum fe_protocol_type {primary, secondary, kldcp}; 51 | static enum fe_protocol_type fe_protocol = secondary; 52 | 53 | /* If zero, then most console memory accesses are relative to page zero. If 54 | non-zero, then console memory accesses are relative to the exec page table. 55 | WAITS wants things to be EBR relative, whereas KLDCP wants things to be 56 | relative to page zero. */ 57 | 58 | static int ebr_relative = 1; 59 | 60 | void 61 | console_reset () 62 | { 63 | signal (SIGIO, SIG_IGN); 64 | signal (SIGVTALRM, SIG_IGN); 65 | if (tcsetattr (console_fd, TCSADRAIN, &otermios)) 66 | printf ("tcsetattr() failed, errno=%d\n", errno); 67 | fcntl (console_fd, F_SETFL, oflags); 68 | } 69 | 70 | void 71 | suspend () 72 | { 73 | print_io_times (); 74 | #ifdef SIGSTOP 75 | kill(getpid(), SIGTSTP); 76 | #else 77 | exit (0); 78 | #endif 79 | } 80 | 81 | /* 82 | * Read a character from the console and return it as the return value. If 83 | * there are no characters available, then return -1. 84 | */ 85 | 86 | static int 87 | read_from_console() 88 | { 89 | int cc; 90 | char cbuf; 91 | 92 | #ifdef __osf__ 93 | { 94 | /* This little hack is necessary because OSF1 will generate a SIGIO each time a 95 | read is done from the terminal. This causes us to get stuck in the SIGIO 96 | signal handler (input_interrupt). The workaround is to avoid doing the 97 | reads unless data is available. */ 98 | #include 99 | int val; 100 | 101 | cc = ioctl (console_fd, FIONREAD, &val); 102 | 103 | if (cc) 104 | printf ("ioctl failed, errno=%d\r\n", errno); 105 | 106 | if (val <= 0) 107 | return -1; 108 | } 109 | #endif 110 | 111 | cc = read (console_fd, &cbuf, sizeof(cbuf)); 112 | 113 | if (cc <= 0) 114 | { 115 | if (cc == 0 || errno == EWOULDBLOCK) 116 | return -1; 117 | printf ("Error reading from tty, errno = %d\n", errno); 118 | console_reset (); 119 | exit (1); 120 | } 121 | 122 | return(cbuf & 0177); 123 | } 124 | 125 | static void 126 | write_to_console (c) 127 | int c; 128 | { 129 | char buf; 130 | 131 | buf = c; 132 | 133 | while (1) 134 | { 135 | int cc; 136 | 137 | cc = write (console_fd, &buf, 1); /* Output a character */ 138 | 139 | if (cc > 0) 140 | break; 141 | 142 | if (cc == 0 143 | || (cc < 0 && errno == EWOULDBLOCK)) 144 | continue; 145 | 146 | perror ("write_to_console: write failed"); 147 | console_reset (); 148 | exit (1); 149 | } 150 | } 151 | 152 | /* Put a character into the console input buffer */ 153 | 154 | static void 155 | putibuf (c) 156 | int c; 157 | { 158 | *consiptr++ = c; 159 | if (consiptr >= consbuf + sizeof(consbuf)) 160 | consiptr = consbuf; 161 | } 162 | 163 | /* Jam the input string into the console input buffer */ 164 | 165 | void 166 | jam_input (p) 167 | char *p; 168 | { 169 | while (*p != '\000') 170 | putibuf (*p++); 171 | set_interrupt (0, DTE_BIT); 172 | } 173 | 174 | /* 175 | * Come here when we get a SIGIO for the console. We read as much stuff as 176 | * possible into the consbuf, and then post an interrupt if the buffer is 177 | * non-empty. 178 | */ 179 | 180 | static int console_flag = 0; /* Non-zero means next char is csl func */ 181 | 182 | static void 183 | input_interrupt() 184 | { 185 | int c; 186 | 187 | while (1) 188 | { 189 | c = read_from_console(); 190 | if (c == -1) 191 | break; 192 | if (console_flag) 193 | { 194 | word36 mem; 195 | 196 | console_flag = 0; 197 | switch (c) 198 | { 199 | case '?': 200 | printf ("Console commands:\r\n\ 201 | ^E - Enter EDDT\r\n\ 202 | s - Deposit 1 in loc 030 (shutdown)\r\n\ 203 | ^T - Status\r\n\ 204 | ^\\ - Insert ^\\\r\n\ 205 | q - Quit (actually suspend) kx10\r\n"); 206 | break; 207 | case '\005': /* ^E for EDDT */ 208 | #ifdef KLDCP 209 | pfetch (030051, mem); 210 | printf ("testpc: 0%o\r\n", lower18(mem)); 211 | #endif 212 | printf("PC/Flags: %o,,%o, Interrupts: %d\r\n", 213 | (pcflags << 5) | (pcsection >> 18), pc, interrupt); 214 | pcsection = 0; 215 | pcflags = 0; 216 | goexec (); 217 | #ifndef KLDCP 218 | pfetch (074, mem); /* .jbddt */ 219 | pc = ldb (35, 18, mem); 220 | #else 221 | pc = 010000; 222 | #endif 223 | break; 224 | case 's': /* loc 30 shutdown */ 225 | case 'S': 226 | dpb (17, 18, 0, mem); 227 | dpb (35, 18, 1, mem); 228 | pstore (030, mem); 229 | break; 230 | case '\024': /* ^T for status info */ 231 | { 232 | sigset_t oldmask; 233 | 234 | sigprocmask (SIG_BLOCK, &blockedsigs, &oldmask); 235 | 236 | printf ("PC/Flags: %o,,%o", 237 | (pcflags << 5) | (pcsection >> 18), pc); 238 | 239 | print_interrupts (); 240 | ! printf ("\r\n"); 241 | 242 | print_pccounts (); 243 | print_io_times (); 244 | 245 | sigprocmask (SIG_SETMASK, &oldmask, NULL); 246 | } 247 | break; 248 | case '\034': /* Self insert */ 249 | putibuf (c); 250 | break; 251 | case 'q': /* q for quit or suspend */ 252 | #ifdef PCHIST 253 | ppc (); 254 | #endif 255 | console_reset(); 256 | printf("\n"); 257 | /* exit(0);*/ 258 | suspend(); 259 | console_init(); 260 | break; 261 | } 262 | } 263 | else if (c == '\034') 264 | console_flag = 1; /* ^\ does console mode */ 265 | else 266 | putibuf (c); 267 | } 268 | 269 | if (fe_protocol == secondary && consiptr != consoptr) 270 | set_interrupt(0, DTE_BIT); 271 | } 272 | 273 | void 274 | console_init () 275 | { 276 | struct termios termios; 277 | struct sigaction action; 278 | sigset_t nullsigmask = {0}; 279 | int newflags; 280 | 281 | action.sa_handler = input_interrupt; 282 | action.sa_mask = nullsigmask; 283 | action.sa_flags = SA_RESTART; 284 | sigaction (SIGIO, &action, NULL); 285 | 286 | action.sa_handler = alarm_handler; 287 | sigaction (SIGVTALRM, &action, NULL); 288 | 289 | if (console_fd < 0) 290 | console_fd = open ("/dev/tty", O_RDWR); 291 | 292 | if (console_fd < 0) 293 | { 294 | perror ("console_init: open failed"); 295 | exit (1); 296 | } 297 | 298 | if (tcgetattr (console_fd, &termios)) { 299 | printf ("tcgetattr() failed: errno=%d\n", errno); 300 | exit (1); 301 | } 302 | 303 | otermios = termios; 304 | 305 | termios.c_iflag = 0; 306 | termios.c_oflag = 0; 307 | termios.c_lflag = 0; 308 | termios.c_cflag &= ~(CSIZE|PARENB); 309 | termios.c_cflag |= CS8; 310 | termios.c_cc[VMIN] = 0; 311 | termios.c_cc[VTIME] = 0; 312 | 313 | if (tcsetattr(console_fd, TCSADRAIN, &termios)) { 314 | printf("tcsetattr() failed: errno=%d\r\n", errno); 315 | exit(1); 316 | } 317 | 318 | fcntl (console_fd, F_SETOWN, getpid()); 319 | 320 | oflags = fcntl (console_fd, F_GETFL, 0); 321 | 322 | #ifdef USE_STREAMS 323 | 324 | /* Enable SIGIO/SIGPOLL */ 325 | 326 | if (ioctl (console_fd, I_SETSIG, S_INPUT|S_RDNORM) < 0) 327 | { 328 | printf ("I_SETSIG failed: %d\r\n", errno); 329 | console_reset (); 330 | exit (1); 331 | } 332 | newflags = oflags | O_NDELAY; /* Turn on non-blocking reads */ 333 | #else 334 | /* Enable SIGIO and non-blocking for non-streams ttys */ 335 | newflags = oflags | FNDELAY | FASYNC; 336 | #endif 337 | 338 | fcntl (console_fd, F_SETFL, newflags); 339 | } 340 | 341 | /* 342 | * Set an alarm for some number of milliseconds in the future. This routine 343 | * is identical to alarm(3), except that it takes it's arg in ms. 344 | */ 345 | 346 | static void 347 | alarm_ms (time) 348 | int time; 349 | { 350 | struct itimerval when; 351 | 352 | timerclear (&when.it_interval); 353 | 354 | when.it_value.tv_sec = time / 1000; 355 | when.it_value.tv_usec = (time % 1000) * 1000; 356 | 357 | setitimer (ITIMER_VIRTUAL, &when, NULL); 358 | } 359 | 360 | static void 361 | alarm_handler () 362 | { 363 | set_interrupt (0, DTE_BIT); 364 | } 365 | 366 | /* Return time in local time zone. Note that time is not corrected for DST. */ 367 | 368 | static void 369 | read_clock () 370 | { 371 | struct tm *tm; 372 | time_t clock; 373 | word36 mem; 374 | 375 | clock = time (NULL); 376 | 377 | tm = localtime (&clock); 378 | 379 | if (!tm) 380 | return; 381 | 382 | if (tm->tm_isdst) 383 | { 384 | clock -= 3600; /* Compensate for DST */ 385 | tm = localtime (&clock); 386 | } 387 | 388 | dpb (4, 5, tm->tm_mday, mem); 389 | dpb (6, 2, 0, mem); 390 | dpb (11, 5, tm->tm_hour, mem); 391 | dpb (13, 2, 0, mem); 392 | dpb (19, 6, tm->tm_min, mem); 393 | dpb (23, 4, tm->tm_mon + 1, mem); 394 | dpb (27, 4, 10, mem); /* Year? */ 395 | dpb (29, 2, 0, mem); 396 | dpb (35, 6, tm->tm_sec, mem); 397 | 398 | if (ebr_relative) 399 | estore (0446, mem); 400 | else 401 | pstore (0446, mem); 402 | } 403 | 404 | /* 405 | * Come here when the -10 rings the DTE's doorbell. We look for a command 406 | * and execute it. 407 | */ 408 | 409 | void 410 | dte_doorbell () 411 | { 412 | word36 mem; 413 | unsigned char cmd, arg; 414 | sigset_t oldmask; 415 | int c; 416 | 417 | if (ebr_relative) 418 | efetch(0451, &mem); /* Get DTECMD */ 419 | else 420 | pfetch(0451, mem); /* [KLDCP] Get DTECMD */ 421 | 422 | cmd = ldb(27, 8, mem); /* Get the command byte */ 423 | arg = ldb(35, 8, mem); /* Get the argument */ 424 | 425 | switch(cmd) 426 | { 427 | case 0: /* [KLDCP] Print a char */ 428 | arg &= 0177; /* Lop off top bit */ 429 | write_to_console (arg); /* Output a character */ 430 | break; 431 | case 01: /* [KLDCP] Processor control */ 432 | switch (arg) 433 | { 434 | case 03: /* End of program */ 435 | printf ("End of program.\r\n"); 436 | genunimp (); 437 | break; 438 | case 04: /* End of pass */ 439 | printf ("End of pass.\r\n"); 440 | genunimp (); 441 | break; 442 | case 05: /* Get main clock control */ 443 | if (ebr_relative) 444 | estore (0450, zero36); 445 | else 446 | pstore (0450, zero36); 447 | break; 448 | default: 449 | printf ("Unimplemented fe processor control function %o\n", arg); 450 | genunimp(); 451 | } 452 | break; 453 | case 02: /* [KLDCP] Various clock functions */ 454 | switch (arg) 455 | { 456 | case 04: /* Set FE date/time */ 457 | break; /* NOT! */ 458 | case 06: /* Read date/time into 0446 */ 459 | read_clock (); 460 | break; 461 | default: 462 | printf ("Unimplemented fe clock function = %o\n", arg); 463 | genunimp(); 464 | } 465 | break; 466 | case 03: /* [KLDCP] Switch functions */ 467 | switch (arg) 468 | { 469 | case 0: /* Read switches (always 405 for now) */ 470 | mem = zero36; 471 | dpb (35, 18, 0405, mem); 472 | if (ebr_relative) 473 | estore (0450, mem); 474 | else 475 | pstore (0450, mem); 476 | break; 477 | default: 478 | printf ("Unimplemented fe switch function %o\n", arg); 479 | genunimp (); 480 | } 481 | break; 482 | case 06: /* [KLDCP] Force tty output? */ 483 | break; 484 | case 07: /* [KLDCP] tty poll */ 485 | sigprocmask (SIG_BLOCK, &blockedsigs, &oldmask); 486 | if (consoptr != consiptr) 487 | { 488 | c = *consoptr++; /* Fetch the oldest character */ 489 | if (consoptr >= consbuf + sizeof(consbuf)) 490 | consoptr = consbuf; 491 | } 492 | else 493 | c = 0; 494 | dpb (35, 8, c, mem); /* Install the input character */ 495 | if (ebr_relative) 496 | estore (0450, mem); /* Put char where -10 can find it (DTEF11) */ 497 | else 498 | pstore (0450, mem); /* Put char where -10 can find it (DTEF11) */ 499 | sigprocmask (SIG_SETMASK, &oldmask, NULL); 500 | break; 501 | case 010: /* Print a char in secondary protocol */ 502 | arg &= 0177; /* Lop off top bit */ 503 | write_to_console (arg); /* Output a character */ 504 | estore (0455, one36); /* Set the done flag for chars (DTEMTD) */ 505 | dteconi |= DTETO10DB; /* Ding dong */ 506 | if (dteconi & 07) 507 | set_interrupt(dteconi, DTE_BIT); 508 | return; 509 | case 011: /* Enter secondary protocol */ 510 | #ifdef undef 511 | printf("[Entering secondary protocol]\r\n"); /* spread the bullshit around liberally */ 512 | #endif /* undef */ 513 | fe_protocol = secondary; 514 | break; 515 | case 012: /* [KLDCP] Enter kldcp protocol */ 516 | fe_protocol = kldcp; 517 | break; 518 | case 013: /* [KLDCP] Read monitor state */ 519 | mem = zero36; 520 | dpb (35, 8, fe_protocol != kldcp, mem); 521 | if (ebr_relative) 522 | estore (0450, mem); 523 | else 524 | pstore (0450, mem); 525 | break; 526 | default: 527 | printf("unimplemented fe command cmd = %o, arg = %o\n", cmd, arg); 528 | genunimp(); 529 | } 530 | 531 | if (ebr_relative) 532 | estore(0444, one36); /* Set the command done flag (DTEFLG) */ 533 | else 534 | pstore(0444, one36); /* [KLDCP] Set the command done flag (DTEFLG) */ 535 | } 536 | 537 | void 538 | dte_interrupt () 539 | { 540 | int c; 541 | word36 mem; 542 | sigset_t oldmask; 543 | 544 | sigprocmask (SIG_BLOCK, &blockedsigs, &oldmask); 545 | 546 | clear_interrupt (0, DTE_BIT); 547 | 548 | if (consiptr != consoptr) 549 | { 550 | efetch(0456, &mem); /* Fetch the magic location (DTEMTI) */ 551 | if (ne36(mem)) /* Is the flag non-zero? */ 552 | alarm_ms (100); /* Yes, try again later */ 553 | else 554 | { /* Flag is clear */ 555 | c = *consoptr++; /* Fetch the oldest character */ 556 | if (consoptr >= consbuf + sizeof(consbuf)) 557 | consoptr = consbuf; 558 | dpb(35, 8, c, mem); /* Install the input character */ 559 | estore(0450, mem); /* Put char where -10 can find it (DTEF11) */ 560 | estore(0456, one36); /* Set the flag (DTEMTI) */ 561 | /* printf("Char: %o\r\n", c); 562 | fflush(stdout); */ 563 | if (consiptr != consoptr) 564 | alarm_ms (100); /* Set alarm if more input pending */ 565 | } 566 | 567 | dteconi |= DTETO10DB; /* Ding dong */ 568 | if (dteconi & 07) 569 | set_interrupt (dteconi, DTE_BIT); 570 | } 571 | 572 | sigprocmask (SIG_SETMASK, &oldmask, NULL); 573 | } 574 | -------------------------------------------------------------------------------- /eacalc.c: -------------------------------------------------------------------------------- 1 | /* Effective address calculation routines for kx10, the PDP-10 emulator. 2 | Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | 20 | /* Calculate the effective address of an EFIW (Extended Format Indirect 21 | * Word). About the only thing that calls this is the code for handling 22 | * two-word global byte pointers. 23 | */ 24 | 25 | addr10 26 | efiw_eacalc(efiw, section) 27 | word36 efiw; 28 | addr10 section; 29 | { 30 | int i=0, x, y, global=0; 31 | addr10 ea; 32 | 33 | ea = section; 34 | 35 | if (ge36 (efiw)) 36 | goto globalind; 37 | 38 | localind: /* Here to handle local indirect words */ 39 | 40 | if (biton (1, efiw)) 41 | illegal_indirect_trap (ea, 1); 42 | 43 | i = biton(13, efiw); 44 | x = ldb(17, 4, efiw); 45 | y = lower18(efiw); 46 | 47 | if (x) 48 | { 49 | if ((ea & SECTMASK) && !biton(0, ea_acref(x)) && ldb(17, 12, ea_acref(x))) 50 | { 51 | ea = (ldb(35, 30, ea_acref(x)) + ((y & 0400000) ? (y | SECTMASK) : y)) 52 | & ADDRMASK; 53 | global = GLOBAL; 54 | } 55 | else 56 | { 57 | ea = (ea & SECTMASK) | ((lower18(ea_acref(x)) + y) & HWORDMASK); 58 | global = 0; 59 | } 60 | } 61 | else 62 | ea = (ea & SECTMASK) | y; 63 | 64 | if (!i) 65 | return(ea | global); 66 | 67 | nextind: /* Here for each indirect word */ 68 | 69 | /* Check for interrupts at each indirect fetch. This prevents a hard 70 | hang when y==. && i is on, ie: `move t1,@.' */ 71 | 72 | if (interrupt >= 0) 73 | { 74 | pc = (pc - 1) & HWORDMASK; /* Continue at this instruction */ 75 | siglongjmp(to_main, 1); 76 | } 77 | 78 | vfetch_ea (ea|global, efiw); 79 | 80 | if ((ea & SECTMASK) == 0) 81 | goto localind; 82 | 83 | if (biton(0, efiw)) 84 | { 85 | global = 0; 86 | goto localind; 87 | } 88 | 89 | /* Global indirect word */ 90 | 91 | globalind: 92 | 93 | global = GLOBAL; 94 | i = biton(1, efiw); 95 | x = ldb(5, 4, efiw); 96 | y = ldb(35, 30, efiw); 97 | 98 | if (x) 99 | ea = (ldb(35, 30, ea_acref(x)) + y) & ADDRMASK; 100 | else 101 | ea = y; 102 | 103 | if (i) 104 | goto nextind; 105 | 106 | return(ea|global); 107 | } 108 | 109 | /* Calculate the effective address of an IFIW (Instruction Format Indirect 110 | * Word) 111 | */ 112 | 113 | addr10 114 | Ieacalc(ir, section) 115 | word36 ir; 116 | addr10 section; 117 | { 118 | int i=0, x, y, global=0; 119 | addr10 ea; 120 | 121 | ea = section; 122 | 123 | localind: /* Here to handle local indirect words */ 124 | 125 | i = biton(13, ir); 126 | x = ldb(17, 4, ir); 127 | y = lower18(ir); 128 | 129 | if (x) 130 | { 131 | if ((ea & SECTMASK) && !biton(0, ea_acref(x)) && ldb(17, 12, ea_acref(x))) 132 | { 133 | ea = (ldb(35, 30, ea_acref(x)) + ((y & 0400000) ? (y | SECTMASK) : y)) 134 | & ADDRMASK; 135 | global = GLOBAL; 136 | } 137 | else 138 | { 139 | ea = (ea & SECTMASK) | ((lower18(ea_acref(x)) + y) & HWORDMASK); 140 | global = 0; 141 | } 142 | } 143 | else 144 | ea = (ea & SECTMASK) | y; 145 | 146 | if (!i) 147 | return(ea | global); 148 | 149 | nextind: /* Here for each indirect word */ 150 | 151 | /* Check for interrupts at each indirect fetch. This prevents a hard 152 | hang when y==. && i is on, ie: `move t1,@.' */ 153 | 154 | if (interrupt >= 0) 155 | { 156 | pc = (pc - 1) & HWORDMASK; /* Continue at this instruction */ 157 | siglongjmp(to_main, 1); 158 | } 159 | 160 | vfetch_ea (ea|global, ir); 161 | 162 | if ((ea & SECTMASK) == 0) 163 | goto localind; 164 | 165 | if (biton(0, ir)) 166 | { 167 | if (biton (1, ir)) 168 | illegal_indirect_trap (ea, 1); 169 | 170 | global = 0; 171 | goto localind; 172 | } 173 | 174 | /* Global indirect word */ 175 | 176 | global = GLOBAL; 177 | i = biton(1, ir); 178 | x = ldb(5, 4, ir); 179 | y = ldb(35, 30, ir); 180 | 181 | if (x) 182 | ea = (ldb(35, 30, ea_acref(x)) + y) & ADDRMASK; 183 | else 184 | ea = y; 185 | 186 | if (i) 187 | goto nextind; 188 | 189 | return(ea|global); 190 | } 191 | 192 | /* This special form of eacalc is required to make jrstf happy */ 193 | 194 | addr10 195 | jrstfeacalc(ir, section, flags) 196 | word36 ir; 197 | addr10 section; 198 | int *flags; 199 | { 200 | int i=0, x, y, global=0; 201 | addr10 ea; 202 | 203 | ea = section; 204 | 205 | localind: /* Here to handle local indirect words */ 206 | 207 | i = biton(13, ir); 208 | x = ldb(17, 4, ir); 209 | y = lower18(ir); 210 | 211 | if (x) 212 | { 213 | *flags = ldb (12, 13, acref(x)); 214 | if ((ea & SECTMASK) && !biton(0, ea_acref(x)) && ldb(17, 12, ea_acref(x))) 215 | { 216 | ea = (ldb(35, 30, ea_acref(x)) + ((y & 0400000) ? (y | SECTMASK) : y)) 217 | & ADDRMASK; 218 | global = GLOBAL; 219 | } 220 | else 221 | { 222 | ea = (ea & SECTMASK) | ((lower18(ea_acref(x)) + y) & HWORDMASK); 223 | global = 0; 224 | } 225 | } 226 | else 227 | ea = (ea & SECTMASK) | y; 228 | 229 | if (!i) 230 | return(ea | global); 231 | 232 | nextind: /* Here for each indirect word */ 233 | 234 | /* Check for interrupts at each indirect fetch. This prevents a hard 235 | hang when y==. && i is on, ie: `jrstf @.' */ 236 | 237 | if (interrupt >= 0) 238 | { 239 | pc = (pc - 1) & HWORDMASK; /* Continue at this instruction */ 240 | siglongjmp(to_main, 1); 241 | } 242 | 243 | vfetch_ea (ea|global, ir); 244 | 245 | *flags = ldb (12, 13, ir); 246 | 247 | if ((ea & SECTMASK) == 0) 248 | goto localind; 249 | 250 | if (biton(0, ir)) 251 | { 252 | if (biton (1, ir)) 253 | illegal_indirect_trap (ea, 1); 254 | 255 | global = 0; 256 | goto localind; 257 | } 258 | 259 | /* Global indirect word */ 260 | 261 | global = GLOBAL; 262 | i = biton(1, ir); 263 | x = ldb(5, 4, ir); 264 | y = ldb(35, 30, ir); 265 | 266 | if (x) 267 | { 268 | *flags = ldb(12, 13, ea_acref(x)); 269 | ea = (ldb(35, 30, ea_acref(x)) + y) & ADDRMASK; 270 | } 271 | else 272 | ea = y; 273 | 274 | if (i) 275 | goto nextind; 276 | 277 | return(ea|global); 278 | } 279 | -------------------------------------------------------------------------------- /ether_bpf.c: -------------------------------------------------------------------------------- 1 | /* BPF Ethernet driver for kx10, the PDP-10 emulator. 2 | Copyright (C) 1994 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | /* Ethernet driver for Berkeley Packet Filter */ 19 | 20 | #include "pdp10.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static int pkf; /* Packet filter fd */ 32 | 33 | int 34 | get_packet (packetp) 35 | unsigned char **packetp; 36 | { 37 | static unsigned char buf[32 * (1550 + sizeof (struct bpf_hdr))]; 38 | static unsigned char *current_packet = buf; 39 | static int buflen = 0; 40 | static struct bpf_hdr *bpf_hdr; 41 | 42 | if (current_packet >= buf + buflen) 43 | { 44 | buflen = read (pkf, buf, sizeof buf); 45 | 46 | if (buflen < 0) 47 | { 48 | perror ("Read error"); 49 | return 0; 50 | } 51 | if (buflen == 0) 52 | return 0; 53 | 54 | current_packet = buf; 55 | } 56 | 57 | bpf_hdr = (struct bpf_hdr *)current_packet; 58 | 59 | *packetp = current_packet + bpf_hdr->bh_hdrlen; 60 | 61 | current_packet += BPF_WORDALIGN (bpf_hdr->bh_hdrlen + bpf_hdr->bh_caplen); 62 | 63 | return bpf_hdr->bh_caplen; 64 | } 65 | 66 | void 67 | send_packet (packet, packetlen) 68 | unsigned char *packet; 69 | int packetlen; 70 | { 71 | int cc; 72 | 73 | cc = write (pkf, packet, packetlen); 74 | 75 | #if 0 76 | printf ("send_packet: sending %d bytes: ", totlen); 77 | { 78 | int i; 79 | for (i = 0; i < totlen; i++) 80 | printf ("%02x ", packet[i]); 81 | printf ("\r\n"); 82 | } 83 | #endif 84 | 85 | if (cc == packetlen) 86 | return; 87 | 88 | if (cc >= 0) 89 | printf ("send_packet sent only %d bytes\r\n", cc); 90 | else 91 | { 92 | perror ("send_packet"); 93 | fprintf (stderr, "\r"); 94 | } 95 | } 96 | 97 | int 98 | init_ether (void) 99 | { 100 | int val; 101 | u_int uval; 102 | u_short bits; 103 | struct endevp endevp; 104 | struct timeval timeval; 105 | extern unsigned char myether[]; 106 | 107 | static struct bpf_insn filters[] = 108 | { 109 | /* IP packets destined for me */ 110 | BPF_STMT (BPF_LD+BPF_H+BPF_ABS, 12), /* IP packet? */ 111 | BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 3), 112 | 113 | BPF_STMT (BPF_LD+BPF_W+BPF_ABS, 30), /* Dest IP address */ 114 | BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, 0x8cae0107, 0, 1), 115 | 116 | BPF_STMT (BPF_RET+BPF_K, 1), /* Accept */ 117 | 118 | /* Or, ARP requests or replies */ 119 | BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_ARP, 0, 3), /* Arp? */ 120 | 121 | BPF_STMT (BPF_LD+BPF_H+BPF_ABS, 20), /* Opcode */ 122 | BPF_JUMP (BPF_JMP+BPF_JSET+BPF_K, ~3, 1, 0), /* Arp request or reply? */ 123 | 124 | BPF_STMT (BPF_RET+BPF_K, 1), /* Accept */ 125 | 126 | BPF_STMT (BPF_RET+BPF_K, 0) /* Reject */ 127 | }; 128 | 129 | static struct bpf_program filters_program = 130 | {sizeof filters / sizeof (struct bpf_insn), filters }; 131 | 132 | pkf = pfopen (NULL, O_RDWR); 133 | 134 | if (pkf < 0) 135 | { 136 | perror ("pkopen failed"); 137 | return 0; 138 | } 139 | 140 | /* Get our ethernet address */ 141 | if (ioctl (pkf, EIOCDEVP, &endevp)) 142 | { 143 | perror ("EIOCDEVP failed"); 144 | close (pkf); 145 | return 0; 146 | } 147 | 148 | memcpy (myether, endevp.end_addr, 6); 149 | 150 | /* We only support 10mb ethernet for now */ 151 | 152 | if (ioctl (pkf, BIOCGDLT, &val) 153 | || val != DLT_EN10MB) 154 | { 155 | perror ("BIOLGDLT failed"); 156 | close (pkf); 157 | return 0; 158 | } 159 | 160 | /* Copy all local packets, enable batch mode, use BPF headers */ 161 | bits = ENBATCH | ENCOPYALL | ENBPFHDR; 162 | if (ioctl (pkf, EIOCMBIS, &bits)) 163 | { 164 | perror ("EIOCMBIS failed"); 165 | close (pkf); 166 | return 0; 167 | } 168 | 169 | /* Give us a SIGUSR1 upon receipt of a packet */ 170 | 171 | signal (SIGUSR1, SIG_IGN); /* Disable receive process */ 172 | 173 | uval = SIGUSR1; 174 | if (ioctl (pkf, EIOCENBS, &uval)) 175 | { 176 | perror ("EIOCENBS failed"); 177 | close (pkf); 178 | return 0; 179 | } 180 | 181 | /* Make the kernel's receive queue bigger */ 182 | 183 | uval = 32; 184 | if (ioctl (pkf, EIOCSETW, &uval)) 185 | { 186 | perror ("EIOCSETW failed"); 187 | close (pkf); 188 | return 0; 189 | } 190 | 191 | /* Set non-blocking reads */ 192 | 193 | timeval.tv_sec = -1; 194 | timeval.tv_usec = -1; 195 | 196 | if (ioctl (pkf, EIOCSRTIMEOUT, &timeval)) 197 | { 198 | perror ("EIOCSRTIMEOUT failed"); 199 | close (pkf); 200 | return 0; 201 | } 202 | 203 | /* Turn on the filters */ 204 | if (ioctl (pkf, BIOCSETF, &filters_program)) 205 | { 206 | perror ("BIOCSETF failed"); 207 | close (pkf); 208 | return 0; 209 | } 210 | 211 | return 1; 212 | } 213 | 214 | -------------------------------------------------------------------------------- /ether_dummy.c: -------------------------------------------------------------------------------- 1 | /* Dummy ethernet driver for kx10, the PDP-10 emulator. 2 | Copyright (C) 1994 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | 20 | int 21 | get_packet (packetp) 22 | unsigned char **packetp; 23 | { 24 | return 0; 25 | } 26 | 27 | void 28 | send_packet (packet, packetlen) 29 | unsigned char *packet; 30 | int packetlen; 31 | { 32 | } 33 | 34 | int 35 | init_ether () 36 | { 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /ether_netbsd.c: -------------------------------------------------------------------------------- 1 | /* BPF Ethernet driver for kx10, the PDP-10 emulator. 2 | Copyright (C) 1994, 1995, 1996 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | /* Ethernet driver for Berkeley Packet Filter */ 19 | 20 | #include "pdp10.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | extern unsigned char myether[]; 37 | 38 | static int pkf; /* Packet filter fd */ 39 | static int bpf_buflen; /* Use this size or else reads fail! */ 40 | 41 | int 42 | get_packet (packetp) 43 | unsigned char **packetp; 44 | { 45 | static unsigned char buf[32 * (1550 + sizeof (struct bpf_hdr))]; 46 | static unsigned char *current_packet = buf; 47 | static int buflen = 0; 48 | static struct bpf_hdr *bpf_hdr; 49 | 50 | if (current_packet >= buf + buflen) 51 | { 52 | #if 0 53 | ioctl (pkf, FIONREAD, &buflen); 54 | if (buflen == 0) 55 | return 0; 56 | #endif 57 | 58 | buflen = read (pkf, buf, bpf_buflen); 59 | 60 | if (buflen < 0) 61 | { 62 | if (errno != EWOULDBLOCK) 63 | perror ("get_packet: read() failed: "); 64 | return 0; 65 | } 66 | if (buflen == 0) 67 | return 0; 68 | 69 | current_packet = buf; 70 | } 71 | 72 | bpf_hdr = (struct bpf_hdr *)current_packet; 73 | 74 | *packetp = current_packet + bpf_hdr->bh_hdrlen; 75 | 76 | current_packet += BPF_WORDALIGN (bpf_hdr->bh_hdrlen + bpf_hdr->bh_caplen); 77 | 78 | return bpf_hdr->bh_caplen; 79 | } 80 | 81 | void 82 | send_packet (packet, packetlen) 83 | unsigned char *packet; 84 | int packetlen; 85 | { 86 | int cc; 87 | 88 | cc = write (pkf, packet, packetlen); 89 | 90 | #if 0 91 | printf ("send_packet: sending %d bytes: ", packetlen); 92 | { 93 | int i; 94 | for (i = 0; i < packetlen; i++) 95 | printf ("%02x ", packet[i]); 96 | printf ("\r\n"); 97 | } 98 | #endif 99 | 100 | if (cc == packetlen) 101 | return; 102 | 103 | if (cc >= 0) 104 | printf ("send_packet sent only %d bytes\r\n", cc); 105 | else 106 | { 107 | perror ("send_packet"); 108 | fprintf (stderr, "\r"); 109 | } 110 | } 111 | 112 | static int 113 | pfopen (name_ignored, flags) 114 | char *name_ignored; 115 | int flags; 116 | { 117 | char name[100]; 118 | int i, tmp; 119 | int fd, sockfd; 120 | struct ifreq ifreq[10]; 121 | struct ifconf ifconf; 122 | struct ifreq tmp_ifreq; 123 | 124 | sockfd = socket (AF_INET, SOCK_DGRAM, 0); 125 | 126 | if (sockfd < 0) 127 | { 128 | perror ("pfopen: socket failed"); 129 | return -1; 130 | } 131 | 132 | ifconf.ifc_len = sizeof (ifreq); 133 | ifconf.ifc_req = ifreq; 134 | i = ioctl (sockfd, SIOCGIFCONF, &ifconf); 135 | 136 | if (i < 0) 137 | { 138 | perror ("pfopen: SIOCGIFCONF failed"); 139 | close (sockfd); 140 | return -1; 141 | } 142 | 143 | for (i = 0; i < ifconf.ifc_len;) 144 | { 145 | struct ifreq *ifreqp; 146 | struct sockaddr_dl *sdp; 147 | 148 | ifreqp = (struct ifreq *)((char *)ifreq + i); 149 | 150 | i += sizeof (ifreqp->ifr_name) + ifreqp->ifr_addr.sa_len; 151 | sdp = (struct sockaddr_dl *)&ifreqp->ifr_addr; 152 | 153 | if (sdp->sdl_family != AF_LINK 154 | && sdp->sdl_type != IFT_ETHER 155 | && sdp->sdl_alen != 6) 156 | continue; /* Not an ethernet */ 157 | 158 | /* Stash away the ethernet address in case this is the one. */ 159 | 160 | memcpy (myether, &sdp->sdl_data[sdp->sdl_nlen], 6); 161 | 162 | tmp_ifreq = *ifreqp; 163 | 164 | tmp = ioctl (sockfd, SIOCGIFFLAGS, &tmp_ifreq); 165 | 166 | if (tmp < 0) 167 | { 168 | perror ("pfopen: SIOCGIFFLAGS failed"); 169 | continue; 170 | } 171 | 172 | #define ON_FLAGS ((short)(IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST)) 173 | #define OFF_FLAGS ((short)(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_NOARP)) 174 | #define CARE_FLAGS ((short)(ON_FLAGS|OFF_FLAGS)) 175 | 176 | /* Make sure that interface is on, not point-to-point, etc... */ 177 | 178 | tmp_ifreq.ifr_flags &= CARE_FLAGS; /* Mask out don't cares */ 179 | 180 | if (tmp_ifreq.ifr_flags == ON_FLAGS) 181 | break; /* Found our interface! */ 182 | } 183 | 184 | close (sockfd); 185 | 186 | if (i >= ifconf.ifc_len) 187 | return -1; /* Couldn't find an interface */ 188 | 189 | for (i = 0; i < 100; i++) 190 | { 191 | sprintf (name, "/dev/bpf%d", i); 192 | 193 | fd = open (name, flags); 194 | 195 | if (fd < 0) 196 | if (errno == ENOENT) 197 | return -1; 198 | else 199 | { 200 | char buf[100]; 201 | 202 | sprintf (buf, "pfopen: open of %s failed", name); 203 | perror (buf); 204 | continue; 205 | } 206 | 207 | tmp = ioctl (fd, BIOCSETIF, &tmp_ifreq); 208 | 209 | if (tmp < 0) 210 | { 211 | perror ("pfopen: BIOCSETIF failed"); 212 | close (fd); 213 | return -1; 214 | } 215 | return fd; 216 | } 217 | 218 | return -1; 219 | } 220 | 221 | int 222 | init_ether (void) 223 | { 224 | int val; 225 | u_int uval; 226 | u_short bits; 227 | struct timeval timeval; 228 | char *myipaddr; 229 | long tmp; 230 | 231 | static struct bpf_insn filters[] = 232 | { 233 | /* IP packets destined for me */ 234 | BPF_STMT (BPF_LD+BPF_H+BPF_ABS, 12), /* IP packet? */ 235 | BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 3), 236 | 237 | BPF_STMT (BPF_LD+BPF_W+BPF_ABS, 30), /* Dest IP address */ 238 | BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, 0x8cae0107, 0, 1), 239 | 240 | BPF_STMT (BPF_RET+BPF_K, 2000), /* Accept */ 241 | 242 | /* Or, ARP requests or replies */ 243 | BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_ARP, 0, 3), /* Arp? */ 244 | 245 | BPF_STMT (BPF_LD+BPF_H+BPF_ABS, 20), /* Opcode */ 246 | BPF_JUMP (BPF_JMP+BPF_JSET+BPF_K, ~3, 1, 0), /* Arp request or reply? */ 247 | 248 | BPF_STMT (BPF_RET+BPF_K, 2000), /* Accept */ 249 | 250 | BPF_STMT (BPF_RET+BPF_K, 0) /* Reject */ 251 | }; 252 | 253 | static struct bpf_program filters_program = 254 | {sizeof filters / sizeof (struct bpf_insn), filters }; 255 | 256 | myipaddr = ConfigGetHostAddress (cfg, NULL, "ip"); 257 | if (!myipaddr) 258 | { 259 | fprintf (stderr, "\n[kx10.config needs to specify an ip address.]\n\n"); 260 | return 0; 261 | } 262 | memcpy (&tmp, myipaddr, 4); 263 | tmp = ntohl (tmp); /* Convert to host byte order */ 264 | filters[3].k = tmp; /* Install in filter */ 265 | 266 | pkf = pfopen (NULL, O_RDWR); 267 | 268 | if (pkf < 0) 269 | { 270 | fprintf (stderr, "\n[KX10 couldn't find a BPF interface. Disabling ethernet emulation.]\n\n"); 271 | return 0; 272 | } 273 | 274 | /* We only support 10mb ethernet for now */ 275 | 276 | if (ioctl (pkf, BIOCGDLT, &val) 277 | || val != DLT_EN10MB) 278 | { 279 | perror ("BIOLGDLT failed"); 280 | close (pkf); 281 | return 0; 282 | } 283 | 284 | /* Give us a SIGUSR1 upon receipt of a packet */ 285 | 286 | signal (SIGUSR1, SIG_IGN); /* Disable receive process */ 287 | 288 | uval = SIGUSR1; 289 | 290 | /* Set non-blocking reads */ 291 | 292 | timeval.tv_sec = -1; 293 | timeval.tv_usec = -1; 294 | 295 | if (ioctl (pkf, BIOCSRTIMEOUT, &timeval)) 296 | { 297 | perror ("BIOCSRTIMEOUT failed"); 298 | close (pkf); 299 | return 0; 300 | } 301 | 302 | val = 1; 303 | if (ioctl (pkf, BIOCIMMEDIATE, &val)) 304 | { 305 | perror ("BIOCIMMEDIATE failed"); 306 | close (pkf); 307 | return 0; 308 | } 309 | 310 | /* Turn on the filters */ 311 | if (ioctl (pkf, BIOCSETF, &filters_program)) 312 | { 313 | perror ("BIOCSETF failed"); 314 | close (pkf); 315 | return 0; 316 | } 317 | 318 | if (ioctl (pkf, BIOCGBLEN, &bpf_buflen)) 319 | { 320 | perror ("BIOCGBLEN failed"); 321 | close (pkf); 322 | return 0; 323 | } 324 | 325 | #if 0 326 | { 327 | int pid; 328 | int ppid; 329 | fd_set readfds; 330 | 331 | ppid = getpid (); 332 | FD_ZERO (&readfds); 333 | 334 | pid = fork (); 335 | if (pid == 0) /* child */ 336 | { 337 | int numfds; 338 | 339 | while (1) 340 | { 341 | FD_SET (pkf, &readfds); 342 | numfds = select(pkf + 1, &readfds, 0, 0, 0); 343 | 344 | if (numfds != 1) 345 | { 346 | if (numfds == -1) 347 | perror ("Select: "); 348 | else 349 | fprintf (stderr, "numfds = %d\n", numfds); 350 | 351 | _exit (1); 352 | } 353 | 354 | if (!FD_ISSET (pkf, &readfds)) 355 | fprintf (stderr, "!FD_ISSET signal process\n"); 356 | 357 | if (kill (ppid, SIGUSR1)) 358 | _exit (0); /* Parent went away. Die quietly */ 359 | } 360 | } 361 | } 362 | #else 363 | val = 1; 364 | if (ioctl (pkf, FIONBIO, &val)) 365 | { 366 | perror ("FIONBIO failed"); 367 | close (pkf); 368 | return 0; 369 | } 370 | 371 | uval = SIGUSR1; 372 | if (ioctl (pkf, BIOCSRSIG, &uval)) 373 | { 374 | perror ("BIOCSRSIG failed"); 375 | close (pkf); 376 | return 0; 377 | } 378 | 379 | val = getpid(); 380 | if (ioctl (pkf, FIOSETOWN, &val)) 381 | { 382 | perror ("FIOSETOWN failed"); 383 | close (pkf); 384 | return 0; 385 | } 386 | 387 | val = 1; 388 | if (ioctl (pkf, FIOASYNC, &val)) 389 | { 390 | perror ("FIOASYNC failed"); 391 | close (pkf); 392 | return 0; 393 | } 394 | 395 | #endif 396 | 397 | return 1; 398 | } 399 | -------------------------------------------------------------------------------- /ether_snit.c: -------------------------------------------------------------------------------- 1 | /* SNIT Ethernet driver for kx10, the PDP-10 emulator. 2 | Copyright (C) 1995 Stu Grossman 3 | This code is written by Bjorn Victor, don't blame Stu! 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 18 | 19 | /* Ethernet driver for SunOS 4 SNIT */ 20 | 21 | #include "pdp10.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define DEV_NIT "/dev/nit" 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | extern unsigned char myether []; 46 | static unsigned long myipaddr; 47 | static char net_device[128]; 48 | 49 | static int if_fd; 50 | 51 | #define BUF_LEN (1550) 52 | 53 | int 54 | get_packet (packetp) 55 | unsigned char **packetp; 56 | { 57 | int buflen; 58 | static unsigned char buf[BUF_LEN][32], *b; 59 | static int bidx = 0; 60 | struct sockaddr sa; 61 | struct strbuf pbuf, dbuf; 62 | int val, flags = 0; 63 | 64 | b = buf[bidx]; 65 | 66 | pbuf.maxlen = sizeof (sa); 67 | pbuf.buf = (char *)&sa; 68 | dbuf.maxlen = BUF_LEN; 69 | dbuf.buf = (char *)b; 70 | 71 | if ((val = getmsg (if_fd, &pbuf, &dbuf, &flags)) != 0) 72 | { 73 | if (val < 0) 74 | { 75 | if (errno != EINTR 76 | && errno != EAGAIN) 77 | perror("getmsg"); 78 | } 79 | return 0; 80 | } 81 | else 82 | { 83 | bidx++; 84 | bidx %= 32; 85 | *packetp = b; 86 | 87 | return dbuf.len; 88 | } 89 | } 90 | 91 | void 92 | send_packet (packet, packetlen) 93 | unsigned char *packet; 94 | int packetlen; 95 | { 96 | struct sockaddr sa; 97 | struct strbuf pbuf, dbuf; 98 | 99 | sa.sa_family = AF_UNSPEC; 100 | memcpy (sa.sa_data, packet, sizeof(sa.sa_data)); 101 | pbuf.len = sizeof (struct sockaddr); 102 | pbuf.buf = (char *) &sa; 103 | dbuf.len = packetlen - 14; 104 | dbuf.buf = (char *)packet + 14; 105 | if (putmsg (if_fd, &pbuf, &dbuf, 0) == 0) 106 | return; 107 | else 108 | { 109 | perror ("send_packet"); 110 | fprintf (stderr, "\r"); 111 | } 112 | return; 113 | } 114 | 115 | static void getconf PARAMS ((void)); 116 | 117 | static void 118 | getconf () 119 | { 120 | FILE *f; 121 | char line[1000]; 122 | struct ether_addr *ea, *ether_aton(); 123 | 124 | if ((f = fopen ("NetConfig", "r")) == NULL) 125 | return; 126 | 127 | for (fgets (line, sizeof (line), f); 128 | !feof (f); 129 | fgets (line, sizeof (line), f)) 130 | { 131 | if (line[0] == '#') 132 | ; 133 | else if (strncmp (line, "ether ", 6) == 0) 134 | { 135 | if ((ea = ether_aton (&line[6])) != NULL) 136 | memcpy(myether,ea->ether_addr_octet,6); 137 | } 138 | else if (strncmp (line, "ip ", 3) == 0) 139 | { 140 | if ((myipaddr = inet_addr (&line[3])) == -1) 141 | myipaddr = 0; 142 | } 143 | else if (strncmp (line, "net ", 4) == 0) 144 | { 145 | line[strlen (line) - 1] = '\0'; 146 | strcpy (net_device, &line[4]); 147 | } 148 | else 149 | fprintf (stderr, "unknown NetConfig keyword: %s\n", line); 150 | } 151 | 152 | fprintf(stderr,"Net Config:\n net %s\n ip %d.%d.%d.%d\n ether %x:%x:%x:%x:%x:%x\n", 153 | net_device, 154 | myipaddr >> 24, (myipaddr >> 16) & 0xff, 155 | (myipaddr >> 8) & 0xff, myipaddr & 0xff, 156 | myether[0], myether[1], myether[2], myether[3], myether[4], myether[5]); 157 | } 158 | 159 | /* This is based on code in the SunOS manual, 160 | and on code from ARNS (A Remote Network Server for AppleTalk). 161 | */ 162 | 163 | int 164 | init_ether () 165 | { 166 | struct strioctl si; 167 | struct ifreq ifr; 168 | struct packetfilt pf; 169 | register u_short *fwp = pf.Pf_Filter; 170 | u_long if_flags = NI_LEN; 171 | 172 | getconf (); 173 | if ((net_device[0] == '\0') || (myipaddr == 0)) 174 | { 175 | fprintf (stderr, "init_ether: not configured\n"); 176 | return 0; 177 | } 178 | 179 | if ((if_fd = open (DEV_NIT, O_RDWR)) == -1) 180 | { 181 | perror ("init_ether: open NIT"); 182 | return 0; 183 | } 184 | 185 | /* Arrange to get discrete messages from the stream. */ 186 | 187 | if ((ioctl (if_fd, I_SRDOPT, (char *)RMSGD)) == -1) 188 | { 189 | perror ("init_ether: RMSGD"); 190 | return 0; 191 | } 192 | 193 | /* Configure the nit device, binding it to the proper underlying interface. */ 194 | 195 | strncpy (ifr.ifr_name, net_device, sizeof ifr.ifr_name); 196 | ifr.ifr_name[sizeof ifr.ifr_name - 1] = '\0'; 197 | 198 | si.ic_cmd = NIOCBIND; 199 | si.ic_timout = INFTIM; 200 | si.ic_len = sizeof ifr; 201 | si.ic_dp = (char *)𝔦 202 | if (ioctl (if_fd, I_STR, (char *)&si) == -1) 203 | { 204 | perror ("init_ether: bind"); 205 | return 0; 206 | } 207 | 208 | #if 0 209 | { 210 | int val = 1; 211 | if (ioctl(if_fd,FIONBIO,&val) == -1) { 212 | perror("init_ether: FIONBIO"); 213 | return 0; 214 | } 215 | val = 1; 216 | if (ioctl(if_fd,FIOASYNC,&val) == -1) { 217 | perror("init_ether: FIOASYNC"); 218 | return 0; 219 | } 220 | 221 | signal(SIGPOLL,SIG_IGN); 222 | 223 | if (ioctl(if_fd,I_SETSIG,S_INPUT) == -1) { 224 | perror("init_ether: I_SETSIG"); 225 | return 0; 226 | } 227 | } 228 | #endif 229 | 230 | 231 | /* Construct a packet filter */ 232 | 233 | #define s_offset(structp, element) (&(((structp)0)->element)) 234 | 235 | memset (&pf, '\000', sizeof(pf)); 236 | 237 | *fwp++ = ENF_PUSHWORD + ((int)s_offset (struct ether_header *, ether_type)) / sizeof (u_short); 238 | *fwp++ = ENF_PUSHLIT | ENF_COR; 239 | *fwp++ = htons(ETHERTYPE_ARP); /* ARP packet => return T immediately */ 240 | 241 | *fwp++ = ENF_PUSHWORD + ((int)s_offset (struct ether_header *, ether_type)) / sizeof (u_short); 242 | *fwp++ = ENF_PUSHLIT | ENF_CAND; 243 | *fwp++ = htons(ETHERTYPE_IP); /* IP packet? Continue, else fail imm. */ 244 | 245 | *fwp++ = ENF_PUSHWORD + 8 + sizeof (struct ether_header) / sizeof (u_short); /* IP dest address field */ 246 | *fwp++ = ENF_PUSHLIT | ENF_CAND; /* first part must match */ 247 | *fwp++ = htons (myipaddr >> 16); 248 | *fwp++ = ENF_PUSHWORD + 9 + sizeof (struct ether_header) / sizeof (u_short); /* IP dest address field part 2 */ 249 | *fwp++ = ENF_PUSHLIT | ENF_EQ; /* and second part */ 250 | *fwp++ = htons (myipaddr & 0xffff); 251 | 252 | 253 | pf.Pf_FilterLen = fwp - &pf.Pf_Filter[0]; 254 | if (pf.Pf_FilterLen > ENMAXFILTERS) 255 | { 256 | fprintf (stderr, "init_ether: Too long filter\n"); 257 | return 0; 258 | } 259 | 260 | si.ic_cmd = NIOCSETF; 261 | si.ic_timout = INFTIM; 262 | si.ic_len = sizeof (pf); 263 | si.ic_dp = (char *)&pf; 264 | 265 | /* Push the packet filter module */ 266 | 267 | if (ioctl (if_fd, I_PUSH, "pf") < 0) 268 | { 269 | perror ("init_ether: push pf"); 270 | return 0; 271 | } 272 | 273 | /* Install the filter */ 274 | 275 | if (ioctl (if_fd, I_STR, (char *)&si) < 0) 276 | { 277 | perror ("init_ether: install pf"); 278 | return 0; 279 | } 280 | 281 | /* Flush the read queue, to get rid of anything that accumulated 282 | before the device reached its final configuration. */ 283 | 284 | if (ioctl (if_fd, I_FLUSH, (char *)FLUSHR) < 0) 285 | { 286 | perror ("init_ether: FLUSH"); 287 | return 0; 288 | } 289 | 290 | /* Give us a SIGUSR1 upon receipt of a packet */ 291 | 292 | #if 1 293 | signal (SIGUSR1, SIG_IGN); 294 | 295 | { 296 | int pid; 297 | int ppid; 298 | fd_set readfds; 299 | 300 | ppid = getpid (); 301 | FD_ZERO (&readfds); 302 | 303 | pid = fork (); 304 | if (pid == 0) 305 | { /* child */ 306 | int numfds; 307 | 308 | while (1) 309 | { 310 | FD_SET (if_fd, &readfds); 311 | numfds = select (if_fd + 1, &readfds, 0, 0, 0); 312 | 313 | if (numfds != 1) 314 | { 315 | if (numfds == -1) 316 | perror ("Ether Select: "); 317 | else 318 | fprintf (stderr, "Ether: numfds = %d\n", numfds); 319 | 320 | _exit (1); 321 | } 322 | 323 | if (!FD_ISSET (if_fd, &readfds)) 324 | fprintf (stderr, "!FD_ISSET signal process\n"); 325 | 326 | if (kill (ppid, SIGUSR1)) 327 | _exit (0); /* Parent went away. Die quietly */ 328 | } 329 | } 330 | } /* End select process */ 331 | #endif 332 | 333 | return 1; 334 | } 335 | -------------------------------------------------------------------------------- /ether_ultrix.c: -------------------------------------------------------------------------------- 1 | /* Ultrix 4.4 Ethernet driver for kx10, the PDP-10 emulator. 2 | Copyright (C) 1995 Stu Grossman 3 | This code is written by Bjorn Victor, based on Stu's bpf code. 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 18 | 19 | /* Ethernet driver for Ultrix 4.4 packet filter */ 20 | 21 | #include "pdp10.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | extern unsigned char myether []; 35 | static unsigned long myipaddr; 36 | static char net_device[128]; 37 | 38 | static int if_fd; 39 | 40 | #define BUF_LEN (1550) 41 | 42 | int 43 | get_packet (packetp) 44 | unsigned char **packetp; 45 | { 46 | static unsigned char buf[32 * (1550 + sizeof (struct enstamp))]; 47 | static unsigned char *current_packet = buf; 48 | static int buflen = 0; 49 | static struct enstamp *bpf_hdr; 50 | 51 | if (current_packet >= buf + buflen) 52 | { 53 | buflen = read (if_fd, buf, sizeof buf); 54 | 55 | if (buflen < 0) 56 | { 57 | perror ("get_packet: Read error"); 58 | return 0; 59 | } 60 | if (buflen == 0) 61 | return 0; 62 | 63 | current_packet = buf; 64 | } 65 | 66 | bpf_hdr = (struct enstamp *)current_packet; 67 | 68 | *packetp = current_packet + bpf_hdr->ens_stamplen; 69 | 70 | current_packet += ENALIGN (bpf_hdr->ens_stamplen + bpf_hdr->ens_count); 71 | 72 | return bpf_hdr->ens_count; 73 | } 74 | 75 | void 76 | send_packet (packet, packetlen) 77 | unsigned char *packet; 78 | int packetlen; 79 | { 80 | int cc; 81 | 82 | cc = write (if_fd, packet, packetlen); 83 | 84 | #if 0 85 | printf ("send_packet: sending %d bytes: ", totlen); 86 | { 87 | int i; 88 | for (i = 0; i < totlen; i++) 89 | printf ("%02x ", packet[i]); 90 | printf ("\r\n"); 91 | } 92 | #endif 93 | 94 | if (cc == packetlen) 95 | return; 96 | 97 | if (cc >= 0) 98 | printf ("send_packet sent only %d bytes\r\n", cc); 99 | else 100 | { 101 | perror ("send_packet"); 102 | fprintf (stderr, "\r"); 103 | } 104 | } 105 | 106 | static void getconf PARAMS ((void)); 107 | 108 | static void 109 | getconf () 110 | { 111 | FILE *f; 112 | char line[1000]; 113 | struct ether_addr *ea, *ether_aton(); 114 | struct in_addr ia; 115 | 116 | if ((f = fopen ("NetConfig", "r")) == NULL) 117 | return; 118 | 119 | net_device[0] = '\0'; /* clear it */ 120 | memset (myether, '\0', 6); /* clear it */ 121 | 122 | for (fgets (line, sizeof (line), f); 123 | !feof (f); 124 | fgets (line, sizeof (line), f)) 125 | { 126 | if (line[0] == '#') 127 | ; 128 | else if (strncmp (line, "ether ", 6) == 0) 129 | { 130 | if ((ea = ether_aton (&line[6])) != NULL) 131 | memcpy(myether,ea->ether_addr_octet,6); 132 | } 133 | else if (strncmp (line, "ip ", 3) == 0) 134 | { 135 | if ((myipaddr = inet_addr (&line[3])) == -1) 136 | myipaddr = 0; 137 | } 138 | else if (strncmp (line, "net ", 4) == 0) 139 | { 140 | line[strlen (line) - 1] = '\0'; 141 | strcpy (net_device, &line[4]); 142 | } 143 | else 144 | fprintf (stderr, "unknown NetConfig keyword: %s\n", line); 145 | } 146 | 147 | ia.s_addr = myipaddr; 148 | 149 | fprintf(stderr,"Net Config:\n net %s\n ip %s\n ether %x:%x:%x:%x:%x:%x\n", 150 | net_device[0] == '\0' ? "(default)" : net_device, 151 | inet_ntoa (ia), 152 | myether[0], myether[1], myether[2], myether[3], myether[4], myether[5]); 153 | } 154 | 155 | /* This is based on the bpf driver by Stu, 156 | and on code from ARNS (A Remote Network Server for AppleTalk). 157 | */ 158 | 159 | int 160 | init_ether () 161 | { 162 | struct enfilter pf; 163 | register u_short *fwp = pf.enf_Filter; 164 | u_int uval; 165 | u_short bits; 166 | struct timeval timeval; 167 | struct endevp endev; 168 | 169 | 170 | getconf (); 171 | if (/*(net_device[0] == '\0') ||*/ (myipaddr == 0)) 172 | { 173 | fprintf (stderr, "init_ether: not configured\n"); 174 | return 0; 175 | } 176 | 177 | if ((if_fd = pfopen (net_device[0] == '\0' ? NULL : net_device, O_RDWR)) < 0) 178 | { 179 | perror ("init_ether: open device"); 180 | return 0; 181 | } 182 | 183 | if (ioctl (if_fd, EIOCDEVP, &endev) < 0) 184 | { 185 | perror ("init_ether: EIOCDEVP failed"); 186 | close (if_fd); 187 | return 0; 188 | } 189 | 190 | if (endev.end_dev_type != ENDT_10MB) 191 | { 192 | fprintf(stderr,"init_ether: unsupported interface type %d\n", 193 | endev.end_dev_type); 194 | close (if_fd); 195 | return 0; 196 | } 197 | 198 | 199 | if (memcmp(myether, endev.end_addr, 6) != 0) 200 | { 201 | if ((myether[0] != 0) || (myether[1] != 0) || (myether[2] != 0) 202 | || (myether[3] != 0) || (myether[4] != 0) || (myether[5] != 0)) 203 | fprintf(stderr, 204 | "init_ether: bad ether address given, should be %x:%x:%x:%x:%x:%x\n", 205 | endev.end_addr[0], endev.end_addr[1], endev.end_addr[2], 206 | endev.end_addr[3], endev.end_addr[4], endev.end_addr[5]); 207 | 208 | memcpy(myether, endev.end_addr, 6); 209 | } 210 | 211 | /* Copy all local packets, enable batch mode, use headers */ 212 | /* XXXX I'm not sure this is good: 213 | timestamping takes a lot of time says the paper /BV */ 214 | bits = ENBATCH | ENCOPYALL | ENTSTAMP; 215 | if (ioctl (if_fd, EIOCMBIS, &bits)) 216 | { 217 | perror ("EIOCMBIS failed"); 218 | close (if_fd); 219 | return 0; 220 | } 221 | 222 | /* Give us a SIGUSR1 upon receipt of a packet */ 223 | 224 | signal (SIGUSR1, SIG_IGN); /* Disable receive process */ 225 | 226 | uval = SIGUSR1; 227 | if (ioctl (if_fd, EIOCENBS, &uval)) 228 | { 229 | perror ("init_ether: EIOCENBS failed"); 230 | close (if_fd); 231 | return 0; 232 | } 233 | 234 | /* Make the kernel's receive queue bigger */ 235 | 236 | uval = 32; 237 | if (ioctl (if_fd, EIOCSETW, &uval)) 238 | { 239 | perror ("init_ether: EIOCSETW failed"); 240 | close (if_fd); 241 | return 0; 242 | } 243 | 244 | /* Set non-blocking reads */ 245 | 246 | timeval.tv_sec = -1; 247 | timeval.tv_usec = -1; 248 | 249 | if (ioctl (if_fd, EIOCSRTIMEOUT, &timeval)) 250 | { 251 | perror ("init_ether: EIOCSRTIMEOUT failed"); 252 | close (if_fd); 253 | return 0; 254 | } 255 | 256 | /* Construct a packet filter */ 257 | 258 | #define s_offset(structp, element) (&(((structp)0)->element)) 259 | 260 | memset (&pf, '\000', sizeof(pf)); 261 | 262 | *fwp++ = ENF_PUSHWORD + ((int)s_offset (struct ether_header *, ether_type)) / sizeof (u_short); 263 | *fwp++ = ENF_PUSHLIT | ENF_COR; 264 | *fwp++ = htons(ETHERTYPE_ARP); /* ARP packet => return T immediately */ 265 | 266 | *fwp++ = ENF_PUSHWORD + ((int)s_offset (struct ether_header *, ether_type)) / sizeof (u_short); 267 | *fwp++ = ENF_PUSHLIT | ENF_CAND; 268 | *fwp++ = htons(ETHERTYPE_IP); /* IP packet? Continue, else fail imm. */ 269 | 270 | *fwp++ = ENF_PUSHWORD + 8 + sizeof (struct ether_header) / sizeof (u_short); /* IP dest address field */ 271 | *fwp++ = ENF_PUSHLIT | ENF_CAND; /* first part must match */ 272 | *fwp++ = htons((htonl (myipaddr)) >> 16); 273 | *fwp++ = ENF_PUSHWORD + 9 + sizeof (struct ether_header) / sizeof (u_short); /* IP dest address field part 2 */ 274 | *fwp++ = ENF_PUSHLIT | ENF_EQ; /* and second part */ 275 | *fwp++ = htons((htonl (myipaddr)) & 0xffff); 276 | 277 | 278 | pf.enf_FilterLen = fwp - &pf.enf_Filter[0]; 279 | if (pf.enf_FilterLen > ENMAXFILTERS) 280 | { 281 | fprintf (stderr, "init_ether: Too long filter\n"); 282 | return 0; 283 | } 284 | 285 | /* Install the filter */ 286 | if (ioctl (if_fd, EIOCSETF, &pf) < 0) 287 | { 288 | perror ("init_ether: install packet filter"); 289 | close (if_fd); 290 | return 0; 291 | } 292 | 293 | /* Flush the read queue, to get rid of anything that accumulated 294 | before the device reached its final configuration. */ 295 | 296 | if (ioctl (if_fd, EIOCFLUSH, 0) < 0) 297 | { 298 | perror ("init_ether: FLUSH"); 299 | return 0; 300 | } 301 | 302 | return 1; 303 | } 304 | -------------------------------------------------------------------------------- /exec.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brouhaha/kx10/6f4f55267176727dc3c34ff60a269fe6dab22a7c/exec.exe -------------------------------------------------------------------------------- /genboole: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | # 3 | # Boolean class instruction generator for kx10, the PDP-10 emulator. 4 | # Copyright (C) 1995 Stu Grossman 5 | # 6 | # This file 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 | # This program 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 program; if not, write to the Free Software 18 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 | # 20 | 21 | # 22 | # This program generates C code for all the boolean instructions. This is 23 | # possible because of the regularity of this part of the instruction set. 24 | # 25 | 26 | # Output the file prologue 27 | 28 | print '#include "pdp10.h"'; 29 | print "\n\n"; 30 | 31 | # Some defs to make life easier 32 | 33 | print '#define andca36(DEST, AC, MEM) andc36 (DEST, AC, MEM) 34 | #define andca36_imm(DEST, AC, IMM) andc36_imm (DEST, AC, IMM) 35 | #define andcm36(DEST, AC, MEM) andc36 (DEST, MEM, AC) 36 | #define andcm36_imm(DEST, AC, IMM) and36_cimm (DEST, AC, IMM) 37 | 38 | #define orca36(DEST, AC, MEM) orc36 (DEST, AC, MEM) 39 | #define orca36_imm(DEST, AC, IMM) orc36_imm (DEST, AC, IMM) 40 | #define orcm36(DEST, AC, MEM) orc36 (DEST, MEM, AC) 41 | #define orcm36_imm(DEST, AC, IMM) or36_cimm (DEST, AC, IMM) 42 | 43 | '; 44 | 45 | # We generate the instructions in opcode order. 46 | 47 | for ($opcode = 0400; $opcode <= 0477; $opcode++) 48 | { 49 | 50 | # First, parse the opcode 51 | 52 | # Operation 53 | 54 | $const = ""; 55 | 56 | $fetch_mem = 1; 57 | $copy_mem = 0; 58 | $copy_ac = 0; 59 | 60 | if (($opcode & 074) == 000) 61 | { 62 | $op = "setz"; 63 | $const = "0"; 64 | $fetch_mem = 0; 65 | } 66 | elsif (($opcode & 074) == 004) 67 | { 68 | $op = "and"; 69 | } 70 | elsif (($opcode & 074) == 010) 71 | { 72 | $op = "andca"; 73 | } 74 | elsif (($opcode & 074) == 014) 75 | { 76 | $op = "setm"; 77 | $copy_mem = 1; 78 | } 79 | elsif (($opcode & 074) == 020) 80 | { 81 | $op = "andcm"; 82 | } 83 | elsif (($opcode & 074) == 024) 84 | { 85 | $op = "seta"; 86 | $fetch_mem = 0; 87 | $copy_ac = 1; 88 | } 89 | elsif (($opcode & 074) == 030) 90 | { 91 | $op = "xor"; 92 | } 93 | elsif (($opcode & 074) == 034) 94 | { 95 | $op = "ior"; 96 | } 97 | elsif (($opcode & 074) == 040) 98 | { 99 | $op = "andcb"; 100 | } 101 | elsif (($opcode & 074) == 044) 102 | { 103 | $op = "eqv"; 104 | } 105 | elsif (($opcode & 074) == 050) 106 | { 107 | $op = "setca"; 108 | $fetch_mem = 0; 109 | } 110 | elsif (($opcode & 074) == 054) 111 | { 112 | $op = "orca"; 113 | } 114 | elsif (($opcode & 074) == 060) 115 | { 116 | $op = "setcm"; 117 | } 118 | elsif (($opcode & 074) == 064) 119 | { 120 | $op = "orcm"; 121 | } 122 | elsif (($opcode & 074) == 070) 123 | { 124 | $op = "orcb"; 125 | } 126 | elsif (($opcode & 074) == 074) 127 | { 128 | $op = "seto"; 129 | $const = "HWORDMASK"; 130 | $fetch_mem = 0; 131 | } 132 | 133 | # Get the mode 134 | 135 | $imm = ""; 136 | $source = "mem"; 137 | if (($opcode & 03) == 0) 138 | { 139 | $mode = ""; 140 | $dest = "AC"; 141 | } 142 | elsif (($opcode & 03) == 01) 143 | { 144 | $mode = "i"; 145 | $imm = "_imm"; 146 | $source = "ea"; 147 | $dest = "AC"; 148 | $fetch_mem = 0; 149 | } 150 | elsif (($opcode & 03) == 02) 151 | { 152 | $mode = "m"; 153 | $dest = "mem"; 154 | } 155 | elsif (($opcode & 03) == 03) 156 | { 157 | $mode = "b"; 158 | $dest = "mem"; 159 | } 160 | 161 | # Now, generate the actual C code 162 | 163 | # First, the prologue 164 | printf "INST(${op}${mode}, 0%o)\n", $opcode; 165 | print "{\n"; 166 | 167 | if (($fetch_mem || $dest eq "mem") && !$copy_ac) 168 | { 169 | printf " word36 mem;\n\n"; 170 | } 171 | 172 | if ($fetch_mem) 173 | { 174 | if (!$copy_mem) 175 | { 176 | printf " vfetch (ea, mem);\n\n"; 177 | } 178 | else 179 | { 180 | printf " vfetch (ea, ${dest});\n"; 181 | } 182 | } 183 | 184 | if ($const ne "") 185 | { 186 | printf " dpb (17, 18, ${const}, ${dest});\n"; 187 | printf " dpb (35, 18, ${const}, ${dest});\n"; 188 | } 189 | elsif ($op eq "and" || ${op} eq "andca" || $op eq "andcm" || $op eq "andcb" || $op eq "xor" 190 | || $op eq "ior" || $op eq "eqv" || $op eq "orca" || $op eq "orcm" || $op eq "orcb") 191 | { 192 | if ($op eq "andcb") 193 | { 194 | $op = "nor"; 195 | } 196 | elsif ($op eq "orcb") 197 | { 198 | $op = "nand"; 199 | } 200 | 201 | print " ${op}36${imm} (${dest}, AC, ${source});\n"; 202 | } 203 | elsif ($op eq "setm") 204 | { 205 | if ($mode eq "i") 206 | { 207 | print ' 208 | /* This is actually xmovei. */ 209 | 210 | dpb (5, 6, 0, AC); /* Clear out unused bits */ 211 | dpb (35, 30, ea, AC); /* Stash the global address */ 212 | 213 | /* if we are in a non-zero section, and ea references an ac, then section 214 | * number is set to 1 */ 215 | 216 | if (pcsection && is_acref(ea)) 217 | dpb(17, 18, 1, AC); 218 | '; 219 | } 220 | } 221 | elsif ($op eq "seta") 222 | { 223 | } 224 | elsif ($op eq "setca") 225 | { 226 | printf " not36 (${dest}, AC);\n"; 227 | } 228 | elsif ($op eq "setcm") 229 | { 230 | if ($mode eq "i") 231 | { 232 | print " dpb (17, 18, HWORDMASK, AC);\n"; 233 | print " dpb (35, 18, ~ea, AC);\n"; 234 | } 235 | else 236 | { 237 | printf " not36 (${dest}, mem);\n"; 238 | } 239 | } 240 | else 241 | { 242 | print stderr "Unknown op '$op'. Aborting.\n"; 243 | exit 1; 244 | } 245 | 246 | if ($mode eq "m" || $mode eq "b") 247 | { 248 | if ($copy_ac) 249 | { 250 | printf " vstore (ea, AC);\n"; 251 | } 252 | else 253 | { 254 | printf "\n vstore (ea, ${dest});\n"; 255 | 256 | if ($mode eq "b") 257 | { 258 | printf "\n AC = mem;\n"; 259 | } 260 | } 261 | } 262 | 263 | # And, finally the epilogue 264 | print "}\n\n" 265 | } 266 | -------------------------------------------------------------------------------- /gendisp: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | # 3 | # Instruction dispatch table generator for kx10, the PDP-10 emulator. 4 | # Copyright (C) 1991, 1992, 1993, 1994, 1995 Stu Grossman 5 | # 6 | # This file 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 | # This program 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 program; if not, write to the Free Software 18 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 | # 20 | 21 | # 22 | # This program will grovel through the i_ files looking for instruction 23 | # definitions. From these it will create a dispatch table, and a name table. 24 | # 25 | 26 | #for ($i = 0; $i < 01000; $i++) { 27 | # $iarray[$i] = sprintf("%03o", $i); 28 | #} 29 | 30 | # First, scan through the files looking for INST and IO_INST declarations, and collect 31 | # them in $iarray. 32 | 33 | 34 | @io_ops = ("blki", "datai", "blko", "datao", 35 | "cono", "coni", "consz", "conso"); 36 | 37 | %name_to_code = ("blki", 0, "datai", 1, "blko", 2, "datao", 3, 38 | "cono", 4, "coni", 5, "consz", 6, "conso", 7); 39 | 40 | @filearray = @ARGV; 41 | 42 | $argsep = '\s*,\s*'; # Argument seperator 43 | 44 | while(<>) { 45 | if (/^INST\((.*)\).*$/) { 46 | ($opname, $opcode) = split($argsep, $1); 47 | $iarray[oct($opcode)] = $opname; 48 | } elsif (/^IO_INST\((.*)\).*$/) { 49 | ($opname, $devname, $devcode) = split($argsep, $1); 50 | $tmp = (oct($devcode) << 1) + $name_to_code{$opname}; 51 | $ioarray{$tmp} = "$opname $devname"; 52 | } 53 | } 54 | 55 | @defined = grep(!/^[0-7]+/, @iarray); 56 | 57 | open(dfile, ">dispatch.c"); 58 | 59 | # First, print the prolog 60 | 61 | print dfile 62 | "#include \"pdp10.h\" 63 | #ifdef comment 64 | This file was automatically generated by gendisp from the following files: 65 | " . 66 | join("\n ", @filearray) . 67 | " 68 | #endif /* comment */ 69 | 70 | "; 71 | 72 | # generate the extern table 73 | 74 | print dfile "extern void "; 75 | 76 | print dfile "i_unimp(),i_io_unimp(),i_luuo(),i_uuo(),"; 77 | 78 | $comma = ""; 79 | foreach $inst (@defined) { 80 | if (defined($inst)) { 81 | print dfile "${comma}i_${inst}()"; 82 | $comma = ","; 83 | } 84 | } 85 | foreach $inst (%ioarray) { 86 | ($op, $dev) = split(/ /, $inst); 87 | print dfile ",i_${op}_${dev}()"; 88 | } 89 | print dfile ";\n\n"; 90 | 91 | # Generate the uuo forward refs 92 | 93 | print dfile "static void "; 94 | 95 | $comma = ""; 96 | for ($i = 0; $i <= 0100; $i++) { 97 | $i_oct = sprintf("%o", $i); 98 | 99 | print dfile "${comma}i_uuo${i_oct}()"; 100 | $comma = ","; 101 | } 102 | print dfile ",i_uuo104 ();\n\n"; 103 | 104 | # Generate the forward ref table for the I/O dispatch routines 105 | 106 | print dfile "extern void "; 107 | 108 | $comma = ""; 109 | for($i = 0700; $i < 01000; $i++) { 110 | $i_oct = sprintf("%o", $i); 111 | print dfile "${comma}i_io${i_oct}()"; 112 | $comma = ","; 113 | } 114 | print dfile ";\n\n"; 115 | 116 | # Now, generate the dispatch vector 117 | 118 | $comma = ""; 119 | print dfile "void (*opdisp[])() = {\n"; 120 | for($i = 0; $i < 01000; $i++) { 121 | $i_oct = sprintf("%o", $i); 122 | if ($iarray[$i] ne "") { 123 | $inst = "i_" . $iarray[$i]; 124 | $imp_count++; 125 | } else { 126 | if ($i >= 1 && $i <= 037) { 127 | $inst = "i_uuo$i_oct"; 128 | $imp_count++; 129 | } elsif ($i == 0 130 | || ($i >= 040 && $i <= 0100) 131 | || $i == 0104) { 132 | $inst = "i_uuo$i_oct"; 133 | $imp_count++; 134 | } elsif (($i >= 0700)) { 135 | $inst = "i_io$i_oct"; 136 | $imp_count++; 137 | } else { 138 | $inst = "i_unimp"; 139 | $unimp_count++; 140 | } 141 | } 142 | $tabs = "\t\t\t"; 143 | $tabs = "\t\t" if (length($inst) >= 8); 144 | $inst = "$inst$tabs/* $i_oct */"; 145 | print dfile "$comma$inst"; 146 | $comma = ",\n"; 147 | } 148 | 149 | print dfile "};\n\n"; 150 | 151 | # uuo and luuo stubs 152 | 153 | for($i = 0; $i <= 0100; $i++) { 154 | $i_oct = sprintf("%o", $i); 155 | 156 | if ($i >= 1 && $i <= 037) { 157 | $l = l; 158 | } else { 159 | $l = ""; 160 | } 161 | 162 | print dfile "static 163 | INST (uuo${i_oct}, 0${i_oct}) 164 | { 165 | i_${l}uuo (0${i_oct}, ac, ea); 166 | } 167 | 168 | "; 169 | } 170 | 171 | print dfile "static 172 | INST (uuo104, 0104) 173 | { 174 | i_uuo (0104, ac, ea); 175 | } 176 | 177 | "; 178 | 179 | # Generate the second level I/O dispatch routines. Basically, all 180 | # that these do is restore the opcode and call i_io(). 181 | 182 | #for($i = 0700; $i <= 0777; $i++) { 183 | # $i_oct = sprintf("%o", $i); 184 | # 185 | # print dfile "static 186 | #INST (io$i_oct, 0${i_oct}) 187 | #{ 188 | # i_io (0${i_oct}, ac, ea); 189 | #} 190 | # 191 | #"; 192 | #} 193 | 194 | #print dfile "/* All I/O instructions come through here. This does the second level dispatch 195 | # through a switch table. */ 196 | # 197 | #static 198 | #SPECIAL_INST (io, 000) 199 | #{ 200 | # if (!(pcflags & (PC_USER | PC_PUBLIC)) || (pcflags & PC_UIO)) 201 | # (*iodisp[((opcode << 4) | ac) & 01777])(ac, ea); 202 | # else 203 | # i_uuo (opcode, ac, ea); 204 | # 205 | #"; 206 | 207 | # Generate the I/O switch table 208 | 209 | #print dfile " switch ((opcode << 2 | ac) & 01777)\n {\n"; 210 | 211 | #for($i = 0; $i <= 01777; $i++) { 212 | # if ($ioarray{$i} ne "") { 213 | # ($op, $dev) = split(/ /, $ioarray{$i}); 214 | # $inst = "i_${op}_${dev}"; 215 | # if ($i == 0) { 216 | # $lastdev = $dev; 217 | # } 218 | # if ($dev ne $lastdev) { 219 | # print dfile "\n"; 220 | # $lastdev = $dev; 221 | # } 222 | # $tmp = sprintf " case 0%o<<2|%o: ${inst} (ac, ea); return;", ($i >> 1) & 0774, $i & 07; 223 | # $tabs = "\t"; 224 | # $tabs = "\t\t" if (length($tmp) < 48); 225 | # print dfile "${tmp}${tabs}/* $op $dev, */\n"; 226 | # } 227 | #} 228 | #print dfile " default: i_io_unimp (opcode, ac, ea); return;\n }\n"; 229 | # 230 | #print dfile "}\n\n"; 231 | 232 | print dfile "char *opnames[] = {"; 233 | 234 | undef(@xarray); 235 | for($i = 0; $i < 0700; $i++) { 236 | if ($iarray[$i] ne "") { 237 | push(@xarray, '"' . $iarray[$i]. '"'); 238 | } else { 239 | if ($i >= 1 && $i <= 037) { 240 | push(@xarray, '"' . "luuo_" . sprintf("%o", $i) . '"'); 241 | } elsif (($i >= 040 && $i <= 0100) 242 | || $i == 0104) { 243 | push(@xarray, '"' . "uuo_" . sprintf("%o", $i) . '"'); 244 | } else { 245 | push(@xarray, '"' . sprintf("%03o", $i) . '"'); 246 | } 247 | } 248 | } 249 | print dfile join(', ', @xarray); 250 | 251 | print dfile "};\n\n" ; 252 | 253 | close(dfile); 254 | 255 | print "[There are $imp_count implemented instructions, and $unimp_count unimplimented instructions.]\n" 256 | -------------------------------------------------------------------------------- /genhw: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | # 3 | # Halfword instruction generator for kx10, the PDP-10 emulator. 4 | # Copyright (C) 1995 Stu Grossman 5 | # 6 | # This file 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 | # This program 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 program; if not, write to the Free Software 18 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 | # 20 | 21 | # 22 | # This program generates C code for all of the (64) halfword instructions. 23 | # This is possible because of the regularity of this part of the instruction 24 | # set. 25 | # 26 | 27 | # Define the sign extension routine 28 | 29 | sub sign_extend { 30 | local ($what) = @_; 31 | local ($pos); 32 | local ($bit); 33 | 34 | if ($ext_hw eq "r") { 35 | $pos = 35; 36 | } else { 37 | $pos = 17; 38 | } 39 | 40 | if ($sign_ext eq "z") { 41 | print "\n dpb ($pos, 18, 0, $what);\n"; 42 | } elsif ($sign_ext eq "o") { 43 | print "\n dpb ($pos, 18, HWORDMASK, $what);\n"; 44 | } elsif ($sign_ext eq "e") { 45 | if ($dst_hw eq "l") { 46 | $bit = 0; 47 | } else { 48 | $bit = 18; 49 | } 50 | print "\n if (biton ($bit, $what))\n"; 51 | print " {\n"; 52 | print " dpb ($pos, 18, HWORDMASK, $what);\n"; 53 | print " }\n"; 54 | print " else\n"; 55 | print " {\n"; 56 | print " dpb ($pos, 18, 0, $what);\n"; 57 | print " }\n"; 58 | } 59 | } 60 | 61 | # Output the file prologue 62 | 63 | print '#include "pdp10.h"'; 64 | print "\n\n"; 65 | 66 | # We generate the instructions in opcode order. 67 | 68 | for ($opcode = 0500; $opcode <= 0577; $opcode++) { 69 | 70 | # First, parse the opcode 71 | 72 | # Dest halfword 73 | if ($opcode & 040) { 74 | $dst_hw = "r"; 75 | } else { 76 | $dst_hw = "l"; 77 | } 78 | 79 | # Source halfword 80 | if ($opcode & 04) { # It's swapped 81 | if ($dst_hw eq "r") { 82 | $src_hw = "l"; 83 | } else { 84 | $src_hw = "r"; 85 | } 86 | } else { # Not swapped 87 | $src_hw = $dst_hw; 88 | } 89 | 90 | # Extension halfword (always the opposite of the dest halfword). 91 | if ($dst_hw eq "r") { 92 | $ext_hw = "l"; 93 | } else { 94 | $ext_hw = "r"; 95 | } 96 | 97 | # Sign extension 98 | if (($opcode & 030) == 0) { 99 | $sign_ext = ""; 100 | } elsif (($opcode & 030) == 010) { 101 | $sign_ext = "z"; 102 | } elsif (($opcode & 030) == 020) { 103 | $sign_ext = "o"; 104 | } elsif (($opcode & 030) == 030) { 105 | $sign_ext = "e"; 106 | } 107 | 108 | # Source and dest 109 | if (($opcode & 03) == 0) { 110 | $mem_op = ""; 111 | } elsif (($opcode & 03) == 01) { 112 | $mem_op = "i"; 113 | } elsif (($opcode & 03) == 02) { 114 | $mem_op = "m"; 115 | } elsif (($opcode & 03) == 03) { 116 | $mem_op = "s"; 117 | } 118 | 119 | 120 | # Now, generate the actual C code for this instruction 121 | 122 | # First, the prologue 123 | printf "INST(h${src_hw}${dst_hw}${sign_ext}${mem_op}, 0%o)\n", $opcode; 124 | print "{\n"; 125 | 126 | # Decide on the major cases based on $mem_op 127 | 128 | if ($mem_op eq "") { # memory => register 129 | print " word36 mem;\n\n"; 130 | 131 | # Fetch the word 132 | print " vfetch (ea, mem);\n"; 133 | 134 | # Load the appropriate halfword into AC 135 | print " hw_${src_hw}${dst_hw} (AC, mem);\n"; 136 | 137 | # Do sign extension. 138 | &sign_extend ("AC"); 139 | 140 | } elsif ($mem_op eq "i") { # immediate 141 | if ($src_hw eq "r") { 142 | $imm_val = "ea"; 143 | } else { 144 | # Loading left half of immediate value. With the exception of hlli (also known 145 | # as xhlli), we just load 0. For hlli, we load the section number. 146 | 147 | if ($dst_hw eq "l" && $sign_ext eq "") { 148 | $imm_val = "(pcsection && is_acref(ea)) ? 1 : (ea & ADDRMASK) >> 18"; 149 | } else { 150 | $imm_val = "0"; 151 | } 152 | } 153 | 154 | if ($dst_hw eq "l") { 155 | $pos = 17; 156 | } else { 157 | $pos = 35; 158 | } 159 | 160 | print " dpb ($pos, 18, $imm_val, AC);\n"; 161 | 162 | # Do sign extension. 163 | &sign_extend ("AC"); 164 | 165 | } elsif ($mem_op eq "m") { # register => memory 166 | print " word36 mem;\n\n"; 167 | 168 | # Fetch the word if necessary. We only need to fetch the word from memory if 169 | # we are preserving the non-destination half. When doing sign extension, zero, 170 | # or one fills, the other half is destroyed, so the fetch is unnecessary. 171 | 172 | if ($sign_ext eq "") { 173 | print " vfetch (ea, mem);\n"; 174 | } 175 | 176 | # Load the appropriate halfword into mem 177 | print " hw_${src_hw}${dst_hw} (mem, AC);\n"; 178 | 179 | # Do sign extension. 180 | &sign_extend ("mem"); 181 | 182 | print "\n vstore (ea, mem);\n"; 183 | 184 | } elsif ($mem_op eq "s") { # memory => memory (also store in reg if reg #= 0) 185 | print " word36 mem;\n\n"; 186 | 187 | # Always fetch the word. 188 | 189 | print " vfetch (ea, mem);\n"; 190 | 191 | # Load the appropriate halfword into mem 192 | print " hw_${src_hw}${dst_hw} (mem, mem);\n"; 193 | 194 | # Do sign extension. 195 | &sign_extend ("mem"); 196 | 197 | print "\n vstore (ea, mem);\n"; 198 | 199 | print "\n if (ac)\n AC = mem;\n"; 200 | } else { # Shouldn't get here 201 | printf stderr "Unknown mem_op '$mem_op'. Aborting.\n"; 202 | exit 1; 203 | } 204 | 205 | 206 | # And, finally the epilogue 207 | print "}\n\n" 208 | } 209 | -------------------------------------------------------------------------------- /genskipjump: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | # 3 | # CAM, CAI, SKIP, JUMP, AOS, AOJ, SOS, SOJ class instruction generator for 4 | # kx10, the PDP-10 emulator. 5 | # Copyright (C) 1995 Stu Grossman 6 | # 7 | # This file 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 | # This program 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 this program; if not, write to the Free Software 19 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 20 | # 21 | 22 | # 23 | # This program generates C code for all of the skip, jump and compare 24 | # instructions. This is possible because of the regularity of this part of the 25 | # instruction set. 26 | # 27 | 28 | # Output the file prologue 29 | 30 | print '#include "pdp10.h"'; 31 | print "\n\n"; 32 | 33 | # We generate the instructions in opcode order. 34 | 35 | for ($opcode = 0300; $opcode <= 0377; $opcode++) { 36 | 37 | # First, parse the opcode 38 | 39 | # Operation 40 | 41 | if (($opcode & 070) == 000) { 42 | $op = "cai"; 43 | } elsif (($opcode & 070) == 010) { 44 | $op = "cam"; 45 | } elsif (($opcode & 070) == 020) { 46 | $op = "jump"; 47 | } elsif (($opcode & 070) == 030) { 48 | $op = "skip"; 49 | } elsif (($opcode & 070) == 040) { 50 | $op = "aoj"; 51 | } elsif (($opcode & 070) == 050) { 52 | $op = "aos"; 53 | } elsif (($opcode & 070) == 060) { 54 | $op = "soj"; 55 | } elsif (($opcode & 070) == 070) { 56 | $op = "sos"; 57 | } 58 | 59 | if ($opcode & 010) { 60 | $mem_fetch = 1; 61 | } else { 62 | $mem_fetch = 0; 63 | } 64 | 65 | if ($opcode & 040) { 66 | if ($opcode & 020) { 67 | $incdec = "s"; 68 | } else { 69 | $incdec = "a"; 70 | } 71 | $mem_store = $mem_fetch; 72 | } else { 73 | $incdec = ""; 74 | $mem_store = 0; 75 | } 76 | 77 | # Comparison type 78 | 79 | if (($opcode & 07) == 000) { 80 | $comp = ""; 81 | } elsif (($opcode & 07) == 01) { 82 | $comp = "l"; 83 | $compmacro = "lt"; 84 | $complement = ""; 85 | } elsif (($opcode & 07) == 02) { 86 | $comp = "e"; 87 | $compmacro = "eq"; 88 | $complement = ""; 89 | } elsif (($opcode & 07) == 03) { 90 | $comp = "le"; 91 | $compmacro = "le"; 92 | $complement = ""; 93 | } elsif (($opcode & 07) == 04) { 94 | $comp = "a"; 95 | } elsif (($opcode & 07) == 05) { 96 | $comp = "ge"; 97 | $compmacro = "lt"; 98 | $complement = "!"; 99 | } elsif (($opcode & 07) == 06) { 100 | $comp = "n"; 101 | $compmacro = "eq"; 102 | $complement = "!"; 103 | } elsif (($opcode & 07) == 07) { 104 | $comp = "g"; 105 | $compmacro = "le"; 106 | $complement = "!"; 107 | } 108 | 109 | # Now, generate the actual C code 110 | 111 | # First, the prologue 112 | printf "INST(${op}${comp}, 0%o)\n", $opcode; 113 | print "{\n"; 114 | 115 | # Fetch memory if necessary 116 | 117 | if ($mem_fetch) { 118 | print " word36 mem;\n\n"; 119 | print " vfetch (ea, mem);\n\n"; 120 | $what = "mem"; 121 | } else { 122 | $what = "AC"; 123 | } 124 | 125 | # Increment/decrement if necessary 126 | 127 | if ($incdec eq "a") { 128 | print " incr36_flags (${what});\n"; 129 | } elsif ($incdec eq "s") { 130 | print " decr36_flags (${what});\n\n"; 131 | } 132 | 133 | if ($mem_store) { 134 | print " vstore (ea, mem);\n"; 135 | } 136 | 137 | # Now do the comparison 138 | 139 | if ($comp eq "a") { 140 | if ($op eq "cai" || $mem_fetch) { 141 | print " incrpc;\n"; 142 | } else { 143 | print " setpc (ea);\n"; 144 | } 145 | } elsif ($comp eq "") { 146 | } else { 147 | if ($op eq "cai") { 148 | print " if (${complement}c${compmacro}_i (AC, ea))\n incrpc;\n"; 149 | } elsif ($op eq "cam") { 150 | print " if (${complement}c${compmacro} (AC, mem))\n incrpc;\n"; 151 | } elsif ($mem_fetch) { 152 | print " if (${complement}${compmacro}36 (mem))\n incrpc;\n"; 153 | } else { 154 | print " if (${complement}${compmacro}36 (AC))\n setpc (ea);\n"; 155 | } 156 | } 157 | 158 | if ($op eq "skip" || $mem_store) { 159 | print " if (ac)\n AC = mem;\n"; 160 | } 161 | 162 | if ($incdec ne "") 163 | { 164 | print " if (pcflags & PC_TRAP1)\n setflags (0);\n"; 165 | } 166 | 167 | # And, finally the epilogue 168 | print "}\n\n" 169 | } 170 | -------------------------------------------------------------------------------- /gentxxx: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | # 3 | # Txxx class instruction generator for kx10, the PDP-10 emulator. 4 | # Copyright (C) 1995 Stu Grossman 5 | # 6 | # This file 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 | # This program 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 program; if not, write to the Free Software 18 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 | # 20 | 21 | # 22 | # This program generates C code for all of the (64) bit test (txxx) 23 | # instructions. This is possible because of the regularity of this part of the 24 | # instruction set. 25 | # 26 | 27 | # Output the file prologue 28 | 29 | print '#include "pdp10.h"'; 30 | print "\n\n"; 31 | 32 | # We generate the instructions in opcode order. 33 | 34 | for ($opcode = 0600; $opcode <= 0677; $opcode++) { 35 | 36 | # First, parse the opcode 37 | 38 | # Source operand 39 | if (($opcode & 011) == 0) { 40 | $src = "r"; 41 | } elsif (($opcode & 011) == 01) { 42 | $src = "l"; 43 | } elsif (($opcode & 011) == 010) { 44 | $src = "d"; 45 | } elsif (($opcode & 011) == 011) { 46 | $src = "s"; 47 | } 48 | 49 | # Modification type 50 | if (($opcode & 060) == 0) { 51 | $mod = "n"; 52 | } elsif (($opcode & 060) == 020) { 53 | $mod = "z"; 54 | } elsif (($opcode & 060) == 040) { 55 | $mod = "c"; 56 | } elsif (($opcode & 060) == 060) { 57 | $mod = "o"; 58 | } 59 | 60 | # Skip condition 61 | 62 | if (($opcode & 06) == 0) { 63 | $skip = ""; 64 | } elsif (($opcode & 06) == 02) { 65 | $skip = "e"; 66 | } elsif (($opcode & 06) == 04) { 67 | $skip = "a"; 68 | } elsif (($opcode & 06) == 06) { 69 | $skip = "n"; 70 | } 71 | 72 | # Now, generate the actual C code 73 | 74 | # First, the prologue 75 | printf "INST(t${src}${mod}${skip}, 0%o)\n", $opcode; 76 | print "{\n"; 77 | 78 | if ($src eq "r" || $src eq "l") { # Source is right or left half 79 | if ($src eq "r") { 80 | $half = "lower18"; 81 | } else { 82 | $half = "upper18"; 83 | } 84 | 85 | # Handle test cases 86 | if ($skip eq "a") { 87 | print " incrpc;\n"; 88 | } elsif ($skip eq "e") { 89 | print " if (($half (AC) & ea) == 0)\n incrpc;\n"; 90 | } elsif ($skip eq "n") { 91 | print " if (($half (AC) & ea) != 0)\n incrpc;\n"; 92 | } 93 | # Now, set, clear or complement bits as appropriate 94 | if ($mod eq "z") { 95 | print " hw_${src}_clear_bits (AC, ea);\n"; 96 | } elsif ($mod eq "c") { 97 | print " hw_${src}_complement_bits (AC, ea);\n"; 98 | } elsif ($mod eq "o") { 99 | print " hw_${src}_set_bits (AC, ea);\n"; 100 | } 101 | } elsif ($src eq "d" || $src eq "s") { # Source is memory or mem swapped 102 | print " word36 mem;\n\n"; 103 | 104 | print " vfetch (ea, mem);\n\n"; 105 | 106 | if ($src eq "s") { # Need to swap the word 107 | $swap = "_swapped"; 108 | } else { 109 | $swap = ""; 110 | } 111 | 112 | # Handle test cases 113 | if ($skip eq "a") { 114 | print " incrpc;\n"; 115 | } elsif ($skip eq "e") { 116 | print " if (!testbits36${swap} (AC, mem))\n incrpc;\n"; 117 | } elsif ($skip eq "n") { 118 | print " if (testbits36${swap} (AC, mem))\n incrpc;\n"; 119 | } 120 | # Now, set, clear or complement bits as appropriate 121 | if ($mod eq "z") { 122 | print " andc36${swap} (AC, mem, AC);\n"; 123 | } elsif ($mod eq "c") { 124 | print " xor36${swap} (AC, mem, AC);\n"; 125 | } elsif ($mod eq "o") { 126 | print " ior36${swap} (AC, mem, AC);\n"; 127 | } 128 | } else { 129 | printf stderr "Unknown src '$src'. Aborting.\n"; 130 | exit 1; 131 | } 132 | 133 | # And, finally the epilogue 134 | print "}\n\n" 135 | } 136 | -------------------------------------------------------------------------------- /i_misc.c: -------------------------------------------------------------------------------- 1 | /* Miscellaneous instructions for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | 20 | void 21 | genunimp () 22 | { 23 | console_reset(); 24 | #ifdef PCHIST 25 | ppc(); 26 | #endif /* PCHIST */ 27 | suspend(); 28 | console_init(); 29 | 30 | return; 31 | } 32 | 33 | SPECIAL_INST(unimp, 000) 34 | { 35 | static char *iocodes[] = {"blki", "datai", "blko", "datao", "cono", 36 | "coni", "consz", "conso"}; 37 | static char *iodevs[] = {"apr", "pi", "pag", "cca", "tim", "mtr"}; 38 | static char *extends[] = {"0", "cmpsl", "cmpse", "cmpsle", "edit", "cmpsge", 39 | "cmpsn", "cmpsg", 40 | "cvtdbo", "cvtdbt", "cvtbdo", "cvsbdt", 41 | "movso", "movst", "movslj", "movsrj", 42 | "xblt", 43 | "gsngl", "gdble", "gdfix", "gfix", "gdfixr", 44 | "gfixr", "dgfltr", "gfltr", "gfsc"}; 45 | extern char *opnames[]; 46 | int dev; 47 | 48 | printf("\r\nUnimplemented instruction at %o: ", pcsection|(pc-1)); 49 | 50 | if (opcode >= 0700) 51 | { /* I/O instruction */ 52 | dev = ((opcode << 1) | (ac >> 3)) & 0177; 53 | 54 | printf("%s ", iocodes[ac & 7]); 55 | 56 | if (dev > 5) 57 | printf("%o", dev << 2); 58 | else 59 | printf("%s", iodevs[dev]); 60 | } 61 | else 62 | printf("%s %o", opnames[opcode], ac); 63 | 64 | printf (", %o\r\n", ea); 65 | 66 | if (opcode == 0123) /* Extend? */ 67 | { 68 | word36 tmp; 69 | int extop; 70 | 71 | vfetch (ea, tmp); 72 | extop = ldb (8, 9, tmp); 73 | 74 | printf("Extend opcode: "); 75 | if (extop < sizeof extends / sizeof (char *)) 76 | printf ("%s\r\n", extends[extop]); 77 | else 78 | printf ("0%o\r\n", extop); 79 | } 80 | 81 | printf ("Flags: %06o,,000000\r\n", pcflags << 5); 82 | 83 | if (pcflags & PC_USER) 84 | { 85 | void i_uuo (); 86 | 87 | i_uuo (opcode, ac, ea); 88 | return; 89 | } 90 | 91 | genunimp(); 92 | } 93 | 94 | SPECIAL_INST(io_unimp, 000) 95 | { 96 | i_unimp (0700 | (opcode >> 4), ac, ea); 97 | } 98 | 99 | SPECIAL_INST(uuo, 0) 100 | { 101 | word36 tmp; 102 | addr10 vec; 103 | 104 | if (!(pagerconi & PAGKL)) 105 | { 106 | vfetch (pc - 1, tmp); 107 | ustore (0424, tmp); /* Store UUO */ 108 | 109 | dpb (17, 18, pcflags << 5, tmp); 110 | dpb (35, 18, pc, tmp); 111 | ustore (0425, tmp); /* PC & flags */ 112 | 113 | dpb (17, 18, pagerdataihigh, tmp); 114 | dpb (35, 18, pagerdatailow, tmp); 115 | ustore (0426, tmp); /* Process context word */ 116 | } 117 | else 118 | { 119 | dpb (17, 18, pcflags << 5, tmp); 120 | dpb (35, 18, (opcode << 9) | (ac << 5) | (prev_pcsection >> 18), tmp); 121 | ustore (0424, tmp); 122 | 123 | dpb (17, 18, pcsection >> 18, tmp); 124 | dpb (35, 18, pc, tmp); 125 | ustore (0425, tmp); 126 | 127 | dpb (5, 6, 0, tmp); 128 | dpb (35, 30, ea, tmp); 129 | ustore (0426, tmp); 130 | 131 | dpb (17, 18, pagerdataihigh, tmp); 132 | dpb (35, 18, pagerdatailow, tmp); 133 | ustore (0427, tmp); 134 | } 135 | 136 | if (trapflags & (PC_TRAP1 | PC_TRAP2)) 137 | vec = 0431; 138 | else 139 | vec = 0430; 140 | 141 | if (pcflags & PC_PUBLIC) 142 | vec += 2; 143 | 144 | if (pcflags & PC_USER) 145 | { 146 | pcflags = PC_PCU; 147 | vec += 4; 148 | goexec (); 149 | } 150 | else 151 | pcflags = 0; 152 | 153 | prev_pcsection = pcsection; 154 | pagerdataihigh = (pagerdataihigh & ~037) | (prev_pcsection >> 18); 155 | 156 | ufetch (vec, &tmp); 157 | 158 | if (!(pagerconi & PAGKL)) 159 | { 160 | pcflags = ldb (12, 13, tmp); 161 | if (pcflags & PC_USER) 162 | gouser (); 163 | setpc (lower18 (tmp)); 164 | } 165 | else 166 | setpc (ldb (35, 30, tmp)); 167 | } 168 | 169 | SPECIAL_INST(luuo, 001) 170 | { 171 | word36 tmp; 172 | word36 ir; 173 | 174 | if (pcsection != 0) 175 | { 176 | if (pcflags & PC_USER) 177 | { 178 | addr10 luuoblock; 179 | 180 | ufetch (0420, &tmp); 181 | 182 | luuoblock = ldb (35, 30, tmp); 183 | 184 | dpb (17, 18, pcflags << 5, tmp); 185 | dpb (35, 18, (opcode << 9) | (ac << 5), tmp); 186 | ustore (luuoblock + 0, tmp); 187 | 188 | dpb (17, 18, pcsection >> 18, tmp); 189 | dpb (35, 18, pc, tmp); 190 | ustore (luuoblock + 1, tmp); 191 | 192 | dpb (5, 6, 0, tmp); 193 | dpb (35, 30, ea, tmp); 194 | ustore (luuoblock + 2, tmp); 195 | 196 | ufetch (luuoblock + 3, &tmp); 197 | setpc (ldb (35, 30, tmp)); 198 | return; 199 | } 200 | else 201 | { 202 | i_uuo (opcode, ac, ea); 203 | return; 204 | } 205 | } 206 | 207 | dpb (17, 18, (opcode << 9) | (ac << 5), tmp); 208 | dpb (35, 18, ea, tmp); 209 | vstore (040, tmp); 210 | 211 | vfetch (041, ir); 212 | opcode = ldb (8, 9, ir); 213 | ac = ldb (12, 4, ir); 214 | ea = ieacalc(ir, ea&SECTMASK); /* Calc ea in the section of the inst */ 215 | (*opdisp[opcode])(ac, ea); /* Recursively call the interpreter */ 216 | } 217 | 218 | INST(pmove, 052) 219 | { 220 | word36 tmp; 221 | 222 | #if 1 223 | if (!(pcflags & (PC_USER | PC_PUBLIC)) || (pcflags & PC_UIO)) 224 | { 225 | vfetch (ea, tmp); /* Fetch physical address */ 226 | 227 | pfetch (ldb (35, 22, tmp), AC); /* Fetch contents */ 228 | } 229 | else 230 | #endif 231 | i_uuo (052, ac, ea); 232 | } 233 | 234 | INST(pmovem, 053) 235 | { 236 | word36 tmp; 237 | 238 | #if 1 239 | if (!(pcflags & (PC_USER | PC_PUBLIC)) || (pcflags & PC_UIO)) 240 | { 241 | vfetch (ea, tmp); /* Fetch physical address */ 242 | 243 | pstore (ldb (35, 22, tmp), AC); /* Store contents */ 244 | } 245 | else 246 | #endif 247 | i_uuo (053, ac, ea); 248 | } 249 | 250 | INST(uuo101, 0101) 251 | { 252 | i_uuo (0101, ac, ea); 253 | } 254 | 255 | INST(extend, 0123) 256 | { 257 | int opcode; 258 | word36 tmp; 259 | 260 | vfetch (ea, tmp); 261 | 262 | opcode = ldb (8, 9, tmp); 263 | 264 | switch (opcode) 265 | { 266 | case 000: /* illegal */ 267 | i_uuo (0123, ac, ea); 268 | return; 269 | case 001: /* cmpsl */ 270 | case 002: /* cmpse */ 271 | case 003: /* cmpsle */ 272 | case 005: /* cmpsge */ 273 | case 006: /* cmpsn */ 274 | case 007: /* cmpsg */ 275 | compare_strings (opcode, ac, ea); 276 | return; 277 | #if 0 278 | case 04: /* edit */ 279 | edit (opcode, ac, ea, tmp); 280 | return; 281 | case 010: /* cvtdbo */ 282 | cvtdbo (opcode, ac, ea, tmp); 283 | return; 284 | case 011: /* cvtdbt */ 285 | cvtdbt (opcode, ac, ea, tmp); 286 | return; 287 | case 012: /* cvtbdo */ 288 | cvtbdo (opcode, ac, ea, tmp); 289 | return; 290 | case 013: /* cvtbdt */ 291 | cvtbdt (opcode, ac, ea, tmp); 292 | return; 293 | #else 294 | case 04: /* edit */ 295 | case 010: /* cvtdbo */ 296 | case 011: /* cvtdbt */ 297 | case 013: /* cvtbdt */ 298 | i_unimp (0123, ac, ea); 299 | return; 300 | #endif 301 | case 012: /* cvtbdo */ 302 | /* CVTBDO Kludge to make EDDT happy!!! */ 303 | dpb(1, 1, 1, ACplus3); /* Set the N bit to make EDDT think that we are a KL */ 304 | return; 305 | case 014: /* movso */ 306 | case 015: /* movst */ 307 | case 016: /* movslj */ 308 | case 017: /* movsrj */ 309 | move_string (opcode, ac, ea, tmp); 310 | return; 311 | case 020: /* xblt */ 312 | { 313 | int length; 314 | addr10 src, dest; 315 | word36 tmp; 316 | 317 | length = ldb(35, 32, AC); 318 | src = ldb(35, 30, ACplus1) | GLOBAL; 319 | dest = ldb(35, 30, ACplus2) | GLOBAL; 320 | 321 | if (length < 0) 322 | { 323 | /* This is very inefficient if we get a page fault in the middle of a big 324 | blt, as we restart the blt from the beginning. */ 325 | 326 | for (; length < 0; length++) 327 | { 328 | src--; 329 | dest--; 330 | 331 | vfetch_2(src, tmp); 332 | vstore_1(dest, tmp); 333 | 334 | incr36 (AC); 335 | decr36 (ACplus1); 336 | decr36 (ACplus2); 337 | } 338 | } 339 | else 340 | { 341 | /* This is very inefficient if we get a page fault in the middle of a big 342 | blt, as we restart the blt from the beginning. */ 343 | 344 | for (; length > 0; length--, src++, dest++) 345 | { 346 | vfetch_2(src, tmp); 347 | vstore_1(dest, tmp); 348 | 349 | decr36 (AC); 350 | incr36 (ACplus1); 351 | incr36 (ACplus2); 352 | } 353 | } 354 | } 355 | return; 356 | default: 357 | i_uuo (0123, ac, ea); 358 | return; 359 | } 360 | } 361 | 362 | INST(jffo, 0243) 363 | { 364 | int bit; 365 | 366 | if (eq36(AC)) 367 | { 368 | ACplus1 = zero36; 369 | return; 370 | } 371 | 372 | for (bit = 0; bit <= 35; bit++) 373 | if (biton(bit, AC)) 374 | break; 375 | 376 | dpb (17, 18, 0, ACplus1); 377 | dpb (35, 18, bit, ACplus1); 378 | 379 | setpc (ea); 380 | } 381 | 382 | INST(uuo247, 0247) 383 | { 384 | i_uuo (0247, ac, ea); 385 | } 386 | 387 | INST(blt, 0251) 388 | { 389 | word36 tmp; 390 | addr10 source, dest; 391 | 392 | source = upper18(AC); 393 | dest = lower18(AC); 394 | 395 | /* Add section to source and dest addresses */ 396 | 397 | #if 1 398 | source |= ea & (GLOBAL|SECTMASK); 399 | #else 400 | source |= pcsection; 401 | #endif 402 | dest |= ea & (GLOBAL|SECTMASK); 403 | 404 | /* This is a crock to make Waits work. It depends upon this to determine 405 | that it's running on a KL. */ 406 | 407 | if (source == dest 408 | && source == ac) 409 | { 410 | AC = zero36; 411 | } 412 | 413 | #if 0 414 | { 415 | int len; 416 | addr10 srcbeg, srclst, dstbeg, dstlst; 417 | word36 mem; 418 | 419 | vfetch_1 (source, mem); 420 | 421 | srcbeg = source & ~GLOBAL; 422 | dstbeg = dest & ~GLOBAL; 423 | dstlst = ea & ~GLOBAL; 424 | 425 | len = dstlst - dstbeg; 426 | srclst = srcbeg + len; 427 | 428 | if ((srcbeg != dstbeg || srclst != dstlst) 429 | && (srcbeg + 1 != dstbeg 430 | || ne36(mem))) 431 | { 432 | if ((srcbeg >= dstbeg && srcbeg <= dstlst) 433 | || (srclst >= dstbeg && srclst <= dstlst)) 434 | printf ("Overlapping BLT at pc %o! src = 0%o=>0%o dst = o%o=>0%o\r\n", 435 | pcsection | pc, srcbeg, srclst, dstbeg, dstlst); 436 | } 437 | } 438 | #endif 439 | 440 | /* This is very inefficient if we get a page fault in the middle of a big 441 | blt, as we restart the blt from the beginning. */ 442 | 443 | while (1) 444 | { 445 | vfetch_1 (source, tmp); 446 | vstore (dest, tmp); 447 | source = increa (source); 448 | dest = increa (dest); 449 | 450 | if (dest > ea) 451 | break; 452 | 453 | dpb (17, 18, source, AC); 454 | dpb (35, 18, dest, AC); 455 | } 456 | 457 | if (((dest - 1) & HWORDMASK) == ac) 458 | return; 459 | 460 | dpb(17, 18, source, AC); 461 | dpb(35, 18, dest, AC); 462 | } 463 | 464 | INST(jrst, 0254) 465 | { 466 | switch (ac) { 467 | case 01: /* Portal. For now, it just acts like jrst */ 468 | { 469 | word36 tmp; 470 | 471 | tmp = map (ea); 472 | 473 | if (biton (6, tmp)) /* Check public bit in map */ 474 | pcflags |= PC_PUBLIC; 475 | else 476 | pcflags &= ~PC_PUBLIC; 477 | } 478 | case 00: /* Normal jrst */ 479 | setpc(ea); 480 | return; 481 | case 02: /* jrstf */ 482 | /* jrstf is one of the ugliest instructions in the whole machine. Doing it 483 | * 'right' would mean that I would have to get the eacalc routine to save 484 | * the last word fetched from either an AC or mem. This would slow down the 485 | * eacalc, so I refuse to put it there. Instead, I have implemented a hacked 486 | * eacalc that can return the right stuff just for jrstf... 487 | */ 488 | { 489 | int jrstfflags; 490 | word36 ir; 491 | 492 | vfetch (pc - 1, ir); /* XXX fix this hack... */ 493 | ea = jrstfeacalc (ir, pcsection, &jrstfflags); 494 | if (pcflags & PC_USER) 495 | pcflags = jrstfflags | PC_USER; 496 | else 497 | { 498 | pcflags = jrstfflags; 499 | if (pcflags & PC_USER) 500 | gouser (); 501 | } 502 | setpc (ea); 503 | if (pcflags & (PC_TRAP1 | PC_TRAP2)) 504 | { 505 | word36 foo; 506 | 507 | vfetch_i (pcsection | pc, foo); 508 | setting_pc = 1; 509 | setflags (0); 510 | setting_pc = 0; 511 | } 512 | } 513 | return; 514 | case 012: /* jen */ 515 | /* jrstf/jen is one of the ugliest instructions in the whole machine. Doing it 516 | * 'right' would mean that I would have to get the eacalc routine to save 517 | * the last word fetched from either an AC or mem. This would slow down the 518 | * eacalc, so I refuse to put it there. Instead, I have implemented a hacked 519 | * eacalc that can return the right stuff just for jrstf... 520 | */ 521 | { 522 | int jrstfflags; 523 | word36 ir; 524 | 525 | if (pcflags & (PC_USER | PC_PUBLIC)) /* User mode? */ 526 | { 527 | i_uuo (0254, ac, ea); /* Yes, bomb him out */ 528 | return; 529 | } 530 | 531 | vfetch (pc - 1, ir); /* XXX fix this hack... */ 532 | ea = jrstfeacalc (ir, pcsection, &jrstfflags); 533 | 534 | pcflags = jrstfflags; 535 | 536 | if (pcflags & PC_USER) 537 | gouser (); 538 | 539 | setpc (ea); 540 | finish_interrupt (); 541 | if (pcflags & (PC_TRAP1 | PC_TRAP2)) 542 | { 543 | word36 foo; 544 | 545 | vfetch_i (pcsection | pc, foo); 546 | setting_pc = 1; 547 | setflags (0); 548 | setting_pc = 0; 549 | } 550 | } 551 | return; 552 | case 04: /* Halt */ 553 | if (pcflags & (PC_USER | PC_PUBLIC)) 554 | { 555 | #ifdef PCHIST 556 | ppc (); 557 | #endif 558 | i_uuo (0254, ac, ea); 559 | return; 560 | } 561 | 562 | printf ("?\007\007Processor executed halt instruction at %0o, new PC is %0o\r\n", 563 | pcsection|(pc-1), ea); 564 | printf ("coni pi = %o,,%o, interrupt = %o\r\n", ppireq, piconi, interrupt); 565 | setpc (ea); 566 | genunimp (); 567 | return; 568 | case 05: /* xjrstf */ 569 | { 570 | word36 flags, newpc; 571 | 572 | vfetch (ea, flags); 573 | 574 | ea = increa (ea); 575 | vfetch (ea, newpc); 576 | setpc (ldb (35, 30, newpc)); 577 | 578 | if (pcflags & PC_USER) 579 | pcflags = ldb (12, 13, flags) | PC_USER; 580 | else 581 | { 582 | prev_pcsection = ldb (35, 5, flags) << 18; 583 | pagerdataihigh = (pagerdataihigh & ~037) | (prev_pcsection >> 18); 584 | pcflags = ldb (12, 13, flags); 585 | if (pcflags & PC_USER) 586 | gouser (); 587 | } 588 | if (pcflags & (PC_TRAP1 | PC_TRAP2)) 589 | { 590 | word36 foo; 591 | 592 | vfetch_i (pcsection | pc, foo); 593 | setting_pc = 1; 594 | setflags (0); 595 | setting_pc = 0; 596 | } 597 | } 598 | return; 599 | case 06: /* xjen */ 600 | { 601 | word36 flags, newpc; 602 | 603 | if (pcflags & PC_USER) /* User mode? */ 604 | { 605 | i_uuo (0254, ac, ea); /* Yes, privileged instruction, bomb */ 606 | return; 607 | } 608 | 609 | vfetch (ea, flags); 610 | 611 | ea = increa (ea); 612 | vfetch (ea, newpc); 613 | setpc (ldb (35, 30, newpc)); 614 | 615 | prev_pcsection = ldb (35, 5, flags) << 18; 616 | pagerdataihigh = (pagerdataihigh & ~037) | (prev_pcsection >> 18); 617 | pcflags = ldb (12, 13, flags); 618 | if (pcflags & PC_USER) 619 | gouser (); 620 | 621 | if (pcflags & (PC_TRAP1 | PC_TRAP2)) 622 | { 623 | word36 foo; 624 | 625 | vfetch_i (pcsection | pc, foo); 626 | setting_pc = 1; 627 | setflags (0); 628 | setting_pc = 0; 629 | } 630 | 631 | finish_interrupt(); /* Clear current interrupt level */ 632 | } 633 | return; 634 | case 07: /* xpcw */ 635 | { 636 | word36 flags, tmppc; 637 | 638 | tmppc = zero36; 639 | dpb (17, 18, pcflags << 5, flags); 640 | dpb (35, 18, prev_pcsection >> 18, flags); 641 | vstore (ea, flags); 642 | 643 | ea = increa (ea); 644 | dpb (35, 30, pcsection | pc, tmppc); 645 | vstore (ea, tmppc); 646 | 647 | ea = increa (ea); 648 | vfetch (ea, flags); 649 | 650 | ea = increa (ea); 651 | vfetch (ea, tmppc); 652 | 653 | if (!(pcflags & PC_USER)) /* Exec mode? */ 654 | { 655 | prev_pcsection = ldb (35, 5, flags) << 18; 656 | pagerdataihigh = (pagerdataihigh & ~037) | (prev_pcsection >> 18); 657 | pcflags = ldb (12, 13, flags); 658 | } 659 | else 660 | pcflags = ldb (12, 13, flags) | PC_USER; 661 | 662 | setpc (ldb (35, 30, tmppc)); 663 | if (pcflags & (PC_TRAP1 | PC_TRAP2)) 664 | { 665 | word36 foo; 666 | 667 | vfetch_i (pcsection | pc, foo); 668 | setting_pc = 1; 669 | setflags (0); 670 | setting_pc = 0; 671 | } 672 | } 673 | return; 674 | case 010: /* Just dismiss interrupt */ 675 | if (pcflags & (PC_USER | PC_PUBLIC)) /* User mode? */ 676 | i_uuo (0254, ac, ea); /* Yes, privileged instruction, bomb */ 677 | else 678 | finish_interrupt(); /* Clear current interrupt level */ 679 | return; 680 | case 014: /* sfm */ 681 | { 682 | word36 tmp; 683 | 684 | dpb(17, 18, pcflags << 5, tmp); 685 | dpb(35, 18, prev_pcsection >> 18, tmp); 686 | vstore(ea, tmp); 687 | } 688 | return; 689 | case 015: /* xjrst */ 690 | { 691 | word36 mem; 692 | 693 | vfetch(ea, mem); 694 | setpc(ldb(35, 30, mem)); 695 | } 696 | return; 697 | default: 698 | i_unimp (0254, ac, ea); 699 | return; 700 | } 701 | } 702 | 703 | INST(jfcl, 0255) 704 | { 705 | if ((ac << 9) & pcflags) 706 | { 707 | pcflags &= ~(ac << 9); 708 | setpc (ea); 709 | } 710 | } 711 | 712 | /*void interpret();*/ 713 | 714 | INST(xct, 0256) 715 | { 716 | int opcode; 717 | word36 ir; 718 | int func; 719 | extern int saved_pcsection; 720 | extern trace_ubr; 721 | 722 | func = ac; 723 | 724 | while (1) 725 | { 726 | vfetch (ea, ir); /* Fetch the instruction */ 727 | opcode = ldb (8, 9, ir); 728 | if (opcode != 0256) /* Is it an xct? */ 729 | break; /* No, no problem */ 730 | 731 | /* We've got an xct of an xct. See if an interrupt has 732 | occurred, otherwise, loop back for the next xct. */ 733 | 734 | if (interrupt < 0) /* Interrupt pending? */ 735 | { /* No, keep on rolling along */ 736 | func = ldb (12, 4, ir); 737 | 738 | ea = ieacalc (ir, ea & SECTMASK); 739 | continue; 740 | } 741 | 742 | pc = (pc - 1) & HWORDMASK; /* Continue at this instruction */ 743 | siglongjmp(to_main, 1); /* Handle the interrupt */ 744 | } 745 | 746 | ac = ldb (12, 4, ir); 747 | 748 | #ifdef PROCESS_TRACING 749 | if (pagerdatailow == trace_ubr 750 | && pcflags & PC_USER) 751 | { 752 | printf (" %o: ", pcsection | pc); 753 | print_instruction (ir); 754 | } 755 | #endif 756 | 757 | if (func == 0 || pcflags & PC_USER) /* Normal xct or user mode */ 758 | { 759 | ea = ieacalc(ir, ea&SECTMASK); /* Calc ea in the section of the inst */ 760 | (*opdisp[opcode])(ac, ea); /* Recursively call the interpreter */ 761 | return; 762 | } 763 | 764 | if (func & 010) 765 | set_previous_eacalc (); 766 | 767 | #if 0 768 | if (opcode == 0123 || opcode == 0251) /* For some reason, extend works differently */ 769 | ea = ieacalc(ir, ea & SECTMASK); 770 | else 771 | ea = ieacalc(ir, prev_pcsection); /* Calc ea in current context, but with 772 | PCS. This is needed to emulate a KL bug 773 | which the monitor depends on. */ 774 | #endif 775 | 776 | if (func & 014) 777 | ea = ieacalc(ir, prev_pcsection); /* Calc ea in current context, but with 778 | PCS. This is needed to emulate a KL bug 779 | which the monitor depends on. */ 780 | else 781 | ea = ieacalc(ir, ea & SECTMASK); 782 | 783 | saved_pcsection = pcsection; 784 | if (func & 03) 785 | pcsection = prev_pcsection; 786 | 787 | set_previous_context_func (func); 788 | 789 | (*opdisp[opcode])(ac, ea); 790 | 791 | pcsection = saved_pcsection; 792 | saved_pcsection = -1; 793 | 794 | clear_previous_context (); 795 | } 796 | 797 | INST(map, 0257) 798 | { 799 | AC = map(ea); 800 | } 801 | 802 | INST(jsr, 0264) 803 | { 804 | word36 tmp; 805 | 806 | tmp = zero36; 807 | 808 | if (pcsection) 809 | { 810 | dpb(35, 30, (pcsection | pc), tmp) /* 30 bit pc for non-zero sections */ 811 | } 812 | else 813 | { 814 | dpb(12, 13, pcflags, tmp); /* PC and flags for sect 0 */ 815 | dpb(35, 18, pc, tmp); 816 | } 817 | 818 | vstore(ea, tmp); /* Store current PC into (ea) */ 819 | 820 | pcflags &= ~(PC_FPD|PC_TRAP1|PC_TRAP2|PC_AFI); 821 | 822 | setpc(increa(ea)); /* Jump to ea+1 */ 823 | } 824 | 825 | INST(jsp, 0265) 826 | { 827 | if (pcsection) 828 | { 829 | dpb (5, 6, 0, AC); 830 | dpb (35, 30, (pcsection | pc), AC); 831 | } 832 | else 833 | { 834 | dpb (17, 18, pcflags << 5, AC); 835 | dpb (35, 18, pc, AC); 836 | } 837 | 838 | pcflags &= ~(PC_FPD|PC_TRAP1|PC_TRAP2|PC_AFI); 839 | 840 | setpc (ea); 841 | } 842 | 843 | INST(jsa, 0266) 844 | { 845 | vstore (ea, AC); 846 | dpb (17, 18, ea, AC); /* ea,, */ 847 | dpb (35, 18, pc, AC); /* ea,,pc */ 848 | 849 | ea = increa (ea); 850 | setpc (ea); /* Jump to ea + 1 */ 851 | } 852 | 853 | INST(jra, 0267) 854 | { 855 | addr10 acaddr; 856 | 857 | acaddr = upper18 (AC); /* Where AC is saved */ 858 | 859 | vfetch (acaddr, AC); /* Restore AC */ 860 | 861 | setpc (ea); /* Jump to EA */ 862 | } 863 | -------------------------------------------------------------------------------- /i_shift.c: -------------------------------------------------------------------------------- 1 | /* Shift and rotate instructions for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994, 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | 20 | INST(ash, 0240) 21 | { 22 | int shiftamount; 23 | 24 | shiftamount = ea & 0377; 25 | if (ea & 0400000) 26 | shiftamount |= ~(unsigned long)0377; 27 | 28 | ashift(shiftamount, AC); 29 | } 30 | 31 | /* We implement rotation by doing a shift left by the amount, and then a 32 | * shift right by 36-amount, and oring the results together. It makes me 33 | * gag too... 34 | */ 35 | 36 | INST(rot, 0241) 37 | { 38 | int shiftamount; 39 | word36 tmp; 40 | 41 | shiftamount = (ea & 0377); 42 | if (ea & 0400000) 43 | shiftamount |= ~(unsigned long)0377; 44 | 45 | if (shiftamount >= 36 46 | || shiftamount <= -36) 47 | shiftamount %= 36; 48 | 49 | tmp = AC; 50 | shift(shiftamount, AC); 51 | if (shiftamount > 0) 52 | { 53 | shift(shiftamount-36, tmp); 54 | } 55 | else 56 | { 57 | shift(shiftamount+36, tmp); 58 | } 59 | ior36(AC, AC, tmp); 60 | } 61 | 62 | INST(lsh, 0242) 63 | { 64 | int shiftamount; 65 | 66 | shiftamount = ea & 0377; 67 | if (ea & 0400000) 68 | shiftamount |= ~(unsigned long)0377; 69 | 70 | shift(shiftamount, AC); 71 | } 72 | 73 | INST(ashc, 0244) 74 | { 75 | int shiftamount; 76 | word36 hiac, loac, tmp; 77 | 78 | shiftamount = ea & 0377; 79 | if (ea & 0400000) 80 | shiftamount |= ~(unsigned long)0377; 81 | 82 | if (shiftamount > 70) 83 | shiftamount = 70; 84 | else if (shiftamount < -70) 85 | shiftamount = -70; 86 | 87 | if (shiftamount == 0) 88 | return; 89 | 90 | hiac = AC; 91 | loac = ACplus1; 92 | 93 | if (shiftamount > 0) 94 | { /* Left shift */ 95 | ashift(shiftamount, hiac); /* Shift the upper part */ 96 | tmp = loac; 97 | dpb(0, 1, 0, tmp); 98 | shift(shiftamount - 35, tmp); /* Create low bits of upper part */ 99 | ior36(hiac, hiac, tmp); /* Install low bits of upper part */ 100 | dpb(0, 1, 0, loac); 101 | shift(shiftamount, loac); /* Shift lower part */ 102 | } 103 | else if (shiftamount < 0) 104 | { /* Right shift */ 105 | dpb(0, 1, 0, loac); 106 | shift(shiftamount, loac); /* Shift lower part */ 107 | tmp = hiac; 108 | dpb(0, 1, 0, tmp); 109 | shift(shiftamount + 35, tmp); /* Create high bits of lower part */ 110 | ior36(loac, loac, tmp); /* Install high bits of lower part */ 111 | ashift(shiftamount, hiac); /* Shift upper part */ 112 | } 113 | 114 | if (biton(0, hiac)) 115 | { 116 | dpb(0, 1, 1, loac); 117 | } 118 | else 119 | { 120 | dpb(0, 1, 0, loac); 121 | } 122 | 123 | AC = hiac; 124 | ACplus1 = loac; 125 | } 126 | 127 | INST(rotc, 0245) 128 | { 129 | int shiftamount; 130 | word36 hiac, loac, tmp; 131 | 132 | shiftamount = ea & 0377; 133 | if (ea & 0400000) 134 | shiftamount |= ~(unsigned long)0377; 135 | 136 | if (shiftamount >= 72 137 | || shiftamount <= -72) 138 | shiftamount %= 72; 139 | 140 | hiac = AC; 141 | loac = ACplus1; 142 | 143 | if (shiftamount > 36) /* big left rotate */ 144 | { 145 | AC = ACplus1; /* shift by 36 */ 146 | shift (shiftamount - 36, AC); /* shift by amt - 36 */ 147 | ACplus1 = zero36; /* zapp the lower part */ 148 | 149 | tmp = hiac; 150 | shift (-(72 - shiftamount), hiac); /* right shift upper */ 151 | shift (36 - (72 - shiftamount), tmp); 152 | shift (-(72 - shiftamount), loac); /* right shift and lower */ 153 | ior36 (loac, loac, tmp); 154 | } 155 | else if (shiftamount >= 0) /* small left rotate */ 156 | { 157 | tmp = ACplus1; 158 | shift (shiftamount, AC); 159 | shift (shiftamount, ACplus1); 160 | shift (-(36 - shiftamount), tmp); 161 | ior36 (AC, AC, tmp); 162 | 163 | shift (-((72 - shiftamount) - 36), hiac); /* shift by amt - 36 */ 164 | loac = hiac; /* shift by 36 */ 165 | hiac = zero36; /* zapp the lower part */ 166 | } 167 | else if (shiftamount >= -36) /* Small right rotate */ 168 | { 169 | tmp = AC; /* Doing right shift */ 170 | shift (shiftamount, AC); 171 | shift (shiftamount, ACplus1); 172 | shift (36 + shiftamount, tmp); 173 | ior36 (ACplus1, ACplus1, tmp); 174 | 175 | shift ((72 + shiftamount) - 36, loac); /* shift by amt - 36 */ 176 | hiac = loac; /* shift by 36 */ 177 | loac = zero36; /* zapp the lower part */ 178 | } 179 | else /* big right rotate */ 180 | { 181 | ACplus1 = AC; /* shift by 36 */ 182 | shift (36 + shiftamount, ACplus1); /* shift by amt - 36 */ 183 | AC = zero36; /* zapp the lower part */ 184 | 185 | tmp = loac; 186 | shift (72 + shiftamount, hiac); /* left shift upper */ 187 | shift (-(36 - (72 + shiftamount)), tmp); 188 | shift (72 + shiftamount, loac); /* left shift and lower */ 189 | ior36 (hiac, hiac, tmp); 190 | } 191 | 192 | ior36 (AC, AC, hiac); 193 | ior36 (ACplus1, ACplus1, loac); 194 | } 195 | 196 | INST(lshc, 0246) 197 | { 198 | int shiftamount; 199 | word36 hiac, loac, tmp; 200 | 201 | hiac = AC; 202 | loac = ACplus1; 203 | 204 | shiftamount = ea & 0377; 205 | if (ea & 0400000) 206 | shiftamount |= ~(unsigned long)0377; 207 | 208 | if (shiftamount >= 72 209 | || shiftamount <= -72) 210 | shiftamount %= 72; 211 | 212 | if (shiftamount > 0) 213 | { /* Left shift */ 214 | shift(shiftamount, hiac); /* Shift the upper part */ 215 | tmp = loac; 216 | shift(shiftamount - 36, tmp); /* Create low bits of upper part */ 217 | ior36(hiac, hiac, tmp); /* Install low bits of upper part */ 218 | shift(shiftamount, loac); /* Shift lower part */ 219 | } 220 | else if (shiftamount < 0) 221 | { /* Right shift */ 222 | shift(shiftamount, loac); /* Shift lower part */ 223 | tmp = hiac; 224 | shift(36 + shiftamount, tmp); /* Create high bits of lower part */ 225 | ior36(loac, loac, tmp); /* Install high bits of upper part */ 226 | shift(shiftamount, hiac); /* Shift upper part */ 227 | } 228 | else 229 | return; 230 | 231 | AC = hiac; 232 | ACplus1 = loac; 233 | } 234 | -------------------------------------------------------------------------------- /i_simple.c: -------------------------------------------------------------------------------- 1 | /* Simple instructions for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994, 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | /* This file contains all of the really simple instructions, like doubleword, 19 | * fullword, and halfword instructions. It also contains the booleans. 20 | */ 21 | 22 | #include "pdp10.h" 23 | 24 | INST(dmove, 0120) 25 | { 26 | word36 tmp, tmp1; 27 | 28 | vfetch(ea, tmp); 29 | ea = increa(ea); 30 | vfetch(ea, tmp1); 31 | 32 | AC = tmp; 33 | ACplus1 = tmp1; 34 | } 35 | 36 | INST(dmovem, 0124) 37 | { 38 | word36 tmp, tmp1; 39 | 40 | tmp = AC; 41 | tmp1 = ACplus1; 42 | 43 | vstore (ea, tmp); 44 | ea = increa (ea); 45 | vstore (ea, tmp1); 46 | } 47 | 48 | INST(move, 0200) 49 | { 50 | vfetch(ea, AC); 51 | } 52 | 53 | INST(movei, 0201) 54 | { 55 | dpb(17, 18, 0, AC); 56 | dpb(35, 18, ea, AC); 57 | } 58 | 59 | INST(movem, 0202) 60 | { 61 | vstore(ea, AC); 62 | } 63 | 64 | INST(moves, 0203) 65 | { 66 | word36 mem; 67 | 68 | vfetch(ea, mem); 69 | vstore(ea, mem); 70 | 71 | if (ac) 72 | AC = mem; 73 | } 74 | 75 | INST(movs, 0204) 76 | { 77 | word36 mem; 78 | 79 | vfetch(ea, mem); 80 | 81 | dpb(17, 18, lower18(mem), AC); 82 | dpb(35, 18, upper18(mem), AC); 83 | } 84 | 85 | INST(movsi, 0205) 86 | { 87 | dpb(17, 18, ea, AC); 88 | dpb(35, 18, 0, AC); 89 | } 90 | 91 | INST(movsm, 0206) 92 | { 93 | word36 tmp; 94 | 95 | dpb(17, 18, lower18(AC), tmp); 96 | dpb(35, 18, upper18(AC), tmp); 97 | 98 | vstore(ea, tmp); 99 | } 100 | 101 | INST(movss, 0207) 102 | { 103 | word36 mem, tmp; 104 | 105 | vfetch(ea, mem); 106 | 107 | dpb(17, 18, lower18(mem), tmp); 108 | dpb(35, 18, upper18(mem), tmp); 109 | 110 | vstore(ea, tmp); 111 | 112 | if (ac) 113 | AC = tmp; 114 | } 115 | 116 | INST(movn, 0210) 117 | { 118 | word36 mem; 119 | 120 | vfetch(ea, mem); 121 | 122 | not36 (AC, mem); 123 | incr36_flags(AC); 124 | 125 | if (pcflags & PC_TRAP1) 126 | setflags (0); 127 | } 128 | 129 | INST(movni, 0211) 130 | { 131 | word36 tmp; 132 | 133 | tmp = zero36; 134 | 135 | dpb(35, 18, ea, tmp); 136 | 137 | not36 (AC, tmp); 138 | incr36_flags(AC); 139 | 140 | if (pcflags & PC_TRAP1) 141 | setflags (0); 142 | } 143 | 144 | INST(movnm, 0212) 145 | { 146 | word36 mem; 147 | 148 | not36 (mem, AC); 149 | incr36_flags(mem); 150 | 151 | vstore(ea, mem); 152 | 153 | if (pcflags & PC_TRAP1) 154 | setflags (0); 155 | } 156 | 157 | INST(movns, 0213) 158 | { 159 | word36 mem; 160 | 161 | vfetch(ea, mem); 162 | 163 | not36 (mem, mem); 164 | incr36_flags(mem); 165 | 166 | vstore(ea, mem); 167 | 168 | if (ac) AC = mem; 169 | 170 | if (pcflags & PC_TRAP1) 171 | setflags (0); 172 | } 173 | 174 | INST(movm, 0214) 175 | { 176 | word36 mem; 177 | 178 | vfetch(ea, mem); 179 | 180 | if (lt36(mem)) 181 | { 182 | not36 (mem, mem); 183 | incr36_flags(mem); 184 | } 185 | 186 | AC = mem; 187 | 188 | if (pcflags & PC_TRAP1) 189 | setflags (0); 190 | } 191 | 192 | INST(movmi, 0215) 193 | { 194 | word36 tmp; 195 | 196 | dpb(17, 18, 0, AC); 197 | dpb(35, 18, ea, AC); 198 | 199 | /* Can never be < 0, so no need to negate or set flags. */ 200 | } 201 | 202 | INST(movmm, 0216) 203 | { 204 | word36 mem; 205 | 206 | mem = AC; 207 | 208 | if (lt36(mem)) 209 | { 210 | not36 (mem, mem); 211 | incr36_flags(mem); 212 | } 213 | 214 | vstore(ea, mem); 215 | 216 | if (pcflags & PC_TRAP1) 217 | setflags (0); 218 | } 219 | 220 | INST(movms, 0217) 221 | { 222 | word36 mem; 223 | 224 | vfetch(ea, mem); 225 | 226 | if (lt36(mem)) 227 | { 228 | not36 (mem, mem); 229 | incr36_flags(mem); 230 | } 231 | 232 | vstore(ea, mem); 233 | 234 | if (ac) AC = mem; 235 | 236 | if (pcflags & PC_TRAP1) 237 | setflags (0); 238 | } 239 | 240 | INST(exch, 0250) 241 | { 242 | word36 tmp; 243 | 244 | vfetch (ea, tmp); /* Get memory contents */ 245 | vstore (ea, AC); /* Store ac contents in memory */ 246 | AC = tmp; /* Put memory into ac */ 247 | } 248 | -------------------------------------------------------------------------------- /i_skipjump.c: -------------------------------------------------------------------------------- 1 | /* Skip and jump instructions for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994, 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | /* This file contains all of the Tx, SKIPx, CAx, JUMPx SOSx, AOSx, SOJx, AOJx, 19 | * SOBJx, and AOBJx instructions. 20 | */ 21 | 22 | #include "pdp10.h" 23 | 24 | INST(aobjp, 0252) 25 | { 26 | register int count, ptr; 27 | 28 | count = upper18(AC) + 1; 29 | ptr = lower18(AC) + 1; 30 | 31 | dpb(17, 18, count, AC); 32 | dpb(35, 18, ptr, AC); 33 | 34 | if (!(count & 0400000)) setpc(ea); 35 | } 36 | 37 | INST(aobjn, 0253) 38 | { 39 | register int count, ptr; 40 | 41 | count = upper18(AC) + 1; 42 | ptr = lower18(AC) + 1; 43 | 44 | dpb(17, 18, count, AC); 45 | dpb(35, 18, ptr, AC); 46 | 47 | if (count & 0400000) setpc(ea); /* Jump if count is negative */ 48 | } 49 | -------------------------------------------------------------------------------- /i_stack.c: -------------------------------------------------------------------------------- 1 | /* Stack instructions for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994, 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | 20 | INST(adjsp, 0105) 21 | { 22 | int count; 23 | addr10 addr; 24 | 25 | count = upper18(AC); 26 | 27 | if (pcsection && count <= 0377777 && count != 0) 28 | { 29 | if (ea & 0400000) 30 | ea |= ~HWORDMASK; /* Sign extend ea */ 31 | else 32 | ea &= HWORDMASK; 33 | 34 | addr = ldb(35, 30, AC); /* Get 30 bit stack addr from ac */ 35 | 36 | addr += ea; /* Decr stack pointer */ 37 | dpb(35, 30, addr, AC); /* Update AC */ 38 | } 39 | else 40 | { 41 | addr = lower18 (AC); /* Get the stack addr */ 42 | 43 | count += ea; /* Adjust the count */ 44 | addr += ea; 45 | 46 | dpb(17, 18, count, AC); /* Update the AC */ 47 | dpb(35, 18, addr, AC); 48 | 49 | /* XXX Deal with stack overflow/underflow */ 50 | } 51 | } 52 | 53 | INST(pushj, 0260) 54 | { 55 | word36 tmp; 56 | int count; 57 | addr10 addr; 58 | 59 | count = upper18(AC); 60 | 61 | if (pcsection && count <= 0377777 && count != 0) 62 | { 63 | dpb (35, 30, (pcsection | pc), tmp); /* 30 bit pc for non-zero sections */ 64 | dpb (5, 6, 0, tmp); 65 | 66 | addr = (ldb(35, 30, AC) + 1) | GLOBAL; 67 | vstore(addr, tmp); 68 | dpb(35, 30, addr, AC); 69 | } 70 | else 71 | { 72 | if (!pcsection) 73 | { 74 | dpb (17, 18, pcflags << 5, tmp); /* Generate PC and flags for sect 0 */ 75 | dpb (35, 18, pc, tmp); 76 | } 77 | else 78 | { 79 | dpb (35, 30, (pcsection | pc), tmp); /* 30 bit pc for non-zero sections */ 80 | dpb (5, 6, 0, tmp); 81 | } 82 | 83 | count++; /* Inc counter and addr, defaulting section */ 84 | addr = pcsection | ((lower18 (AC) + 1) & HWORDMASK); 85 | 86 | vstore(addr, tmp); /* Store PC & flags into addr */ 87 | 88 | dpb(17, 18, count, AC); /* Update the AC */ 89 | dpb(35, 18, addr, AC); 90 | 91 | if ((count & HWORDMASK) == 0) 92 | { /* Check for overflow trap */ 93 | printf("Got a PDL OV!!!\n"); 94 | } 95 | } 96 | 97 | pcflags &= ~(PC_FPD|PC_TRAP1|PC_TRAP2|PC_AFI); 98 | 99 | setpc(ea); /* Jump to ea */ 100 | } 101 | 102 | INST(push, 0261) 103 | { 104 | word36 mem; 105 | int count; 106 | addr10 addr; 107 | 108 | vfetch(ea, mem); /* Get object of push */ 109 | 110 | count = upper18(AC); 111 | 112 | if (pcsection && count <= 0377777 && count != 0) 113 | { 114 | addr = (ldb(35, 30, AC) + 1) | GLOBAL; 115 | vstore_1(addr, mem); 116 | dpb(35, 30, addr, AC); 117 | } 118 | else 119 | { 120 | count++; /* Inc counter and addr, defaulting section */ 121 | addr = pcsection | ((lower18 (AC) + 1) & HWORDMASK); 122 | 123 | vstore_1(addr, mem); /* Store (ea) into addr */ 124 | 125 | dpb(17, 18, count, AC); /* Update the AC */ 126 | dpb(35, 18, addr, AC); 127 | 128 | if ((count & HWORDMASK) == 0) 129 | { /* Check for overflow trap */ 130 | printf("Got a PDL OV!!!\n"); 131 | } 132 | } 133 | } 134 | 135 | INST(pop, 0262) 136 | { 137 | word36 mem; 138 | int count; 139 | addr10 addr; 140 | 141 | count = upper18(AC); 142 | 143 | if (pcsection && count <= 0377777 && count != 0) 144 | { 145 | addr = ldb(35, 30, AC); /* Get 30 bit stack addr from ac */ 146 | vfetch_1(addr | GLOBAL, mem); /* Get word from stack */ 147 | vstore(ea, mem); /* Store it into (ea)*/ 148 | 149 | addr--; /* Decr stack pointer */ 150 | dpb(35, 30, addr, AC); /* Update AC */ 151 | } 152 | else 153 | { 154 | addr = lower18(AC); /* Get the addr to get the word from */ 155 | 156 | vfetch_1(pcsection | addr, mem); /* Fetch word from the stack */ 157 | vstore(ea, mem); /* Store it into (ea)*/ 158 | 159 | count--; /* Decrement count and addr */ 160 | addr = pcsection | ((addr - 1) & HWORDMASK); 161 | 162 | dpb(17, 18, count, AC); /* Update the AC */ 163 | dpb(35, 18, addr, AC); 164 | 165 | if ((count & HWORDMASK) == HWORDMASK) 166 | { /* Did we underflow? Trap */ 167 | printf("Got a PDL underflow!!!\n"); 168 | } 169 | } 170 | } 171 | 172 | INST(popj, 0263) 173 | { 174 | word36 tmp; 175 | int count; 176 | addr10 addr; 177 | 178 | count = upper18(AC); 179 | 180 | if (pcsection && count <= 0377777 && count != 0) 181 | { 182 | addr = ldb(35, 30, AC); /* Get 30 bit stack addr from ac */ 183 | vfetch(addr | GLOBAL, tmp); /* Get pc from stack addr */ 184 | 185 | addr--; /* Decr stack pointer */ 186 | dpb(35, 30, addr, AC); /* Update AC */ 187 | 188 | setpc(ldb(35, 30, tmp)); /* Load up 30 bit PC */ 189 | } 190 | else 191 | { 192 | addr = lower18 (AC); /* Get the addr to get the PC from */ 193 | 194 | vfetch(pcsection | addr, tmp); /* Fetch PC and flags from addr */ 195 | 196 | count--; /* Decrement count and addr */ 197 | addr = pcsection | ((addr - 1) & HWORDMASK); 198 | 199 | dpb(17, 18, count, AC); /* Update the AC */ 200 | dpb(35, 18, addr, AC); 201 | 202 | if ((count & HWORDMASK) == HWORDMASK) 203 | { /* Did we underflow? */ 204 | /* trap */ 205 | printf("Got a PDL underflow!!!\n"); 206 | } 207 | 208 | if (pcsection == 0) 209 | setpc(lower18 (tmp)); /* PC from lower half */ 210 | else 211 | setpc(ldb(35, 30, tmp)); /* Load up 30 bit PC */ 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5. 5 | # 6 | # Calling this script install-sh is preferred over install.sh, to prevent 7 | # `make' implicit rules from creating a file called install from it 8 | # when there is no Makefile. 9 | # 10 | # This script is compatible with the BSD install script, but was written 11 | # from scratch. 12 | # 13 | 14 | 15 | # set DOITPROG to echo to test this script 16 | 17 | # Don't use :- since 4.3BSD and earlier shells don't like it. 18 | doit="${DOITPROG-}" 19 | 20 | 21 | # put in absolute paths if you don't have them in your path; or use env. vars. 22 | 23 | mvprog="${MVPROG-mv}" 24 | cpprog="${CPPROG-cp}" 25 | chmodprog="${CHMODPROG-chmod}" 26 | chownprog="${CHOWNPROG-chown}" 27 | chgrpprog="${CHGRPPROG-chgrp}" 28 | stripprog="${STRIPPROG-strip}" 29 | rmprog="${RMPROG-rm}" 30 | mkdirprog="${MKDIRPROG-mkdir}" 31 | 32 | tranformbasename="" 33 | transform_arg="" 34 | instcmd="$mvprog" 35 | chmodcmd="$chmodprog 0755" 36 | chowncmd="" 37 | chgrpcmd="" 38 | stripcmd="" 39 | rmcmd="$rmprog -f" 40 | mvcmd="$mvprog" 41 | src="" 42 | dst="" 43 | dir_arg="" 44 | 45 | while [ x"$1" != x ]; do 46 | case $1 in 47 | -c) instcmd="$cpprog" 48 | shift 49 | continue;; 50 | 51 | -d) dir_arg=true 52 | shift 53 | continue;; 54 | 55 | -m) chmodcmd="$chmodprog $2" 56 | shift 57 | shift 58 | continue;; 59 | 60 | -o) chowncmd="$chownprog $2" 61 | shift 62 | shift 63 | continue;; 64 | 65 | -g) chgrpcmd="$chgrpprog $2" 66 | shift 67 | shift 68 | continue;; 69 | 70 | -s) stripcmd="$stripprog" 71 | shift 72 | continue;; 73 | 74 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 75 | shift 76 | continue;; 77 | 78 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 79 | shift 80 | continue;; 81 | 82 | *) if [ x"$src" = x ] 83 | then 84 | src=$1 85 | else 86 | # this colon is to work around a 386BSD /bin/sh bug 87 | : 88 | dst=$1 89 | fi 90 | shift 91 | continue;; 92 | esac 93 | done 94 | 95 | if [ x"$src" = x ] 96 | then 97 | echo "install: no input file specified" 98 | exit 1 99 | else 100 | true 101 | fi 102 | 103 | if [ x"$dir_arg" != x ]; then 104 | dst=$src 105 | src="" 106 | 107 | if [ -d $dst ]; then 108 | instcmd=: 109 | else 110 | instcmd=mkdir 111 | fi 112 | else 113 | 114 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 115 | # might cause directories to be created, which would be especially bad 116 | # if $src (and thus $dsttmp) contains '*'. 117 | 118 | if [ -f $src -o -d $src ] 119 | then 120 | true 121 | else 122 | echo "install: $src does not exist" 123 | exit 1 124 | fi 125 | 126 | if [ x"$dst" = x ] 127 | then 128 | echo "install: no destination specified" 129 | exit 1 130 | else 131 | true 132 | fi 133 | 134 | # If destination is a directory, append the input filename; if your system 135 | # does not like double slashes in filenames, you may need to add some logic 136 | 137 | if [ -d $dst ] 138 | then 139 | dst="$dst"/`basename $src` 140 | else 141 | true 142 | fi 143 | fi 144 | 145 | ## this sed command emulates the dirname command 146 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 147 | 148 | # Make sure that the destination directory exists. 149 | # this part is taken from Noah Friedman's mkinstalldirs script 150 | 151 | # Skip lots of stat calls in the usual case. 152 | if [ ! -d "$dstdir" ]; then 153 | defaultIFS=' 154 | ' 155 | IFS="${IFS-${defaultIFS}}" 156 | 157 | oIFS="${IFS}" 158 | # Some sh's can't handle IFS=/ for some reason. 159 | IFS='%' 160 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 161 | IFS="${oIFS}" 162 | 163 | pathcomp='' 164 | 165 | while [ $# -ne 0 ] ; do 166 | pathcomp="${pathcomp}${1}" 167 | shift 168 | 169 | if [ ! -d "${pathcomp}" ] ; 170 | then 171 | $mkdirprog "${pathcomp}" 172 | else 173 | true 174 | fi 175 | 176 | pathcomp="${pathcomp}/" 177 | done 178 | fi 179 | 180 | if [ x"$dir_arg" != x ] 181 | then 182 | $doit $instcmd $dst && 183 | 184 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && 185 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && 186 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && 187 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi 188 | else 189 | 190 | # If we're going to rename the final executable, determine the name now. 191 | 192 | if [ x"$transformarg" = x ] 193 | then 194 | dstfile=`basename $dst` 195 | else 196 | dstfile=`basename $dst $transformbasename | 197 | sed $transformarg`$transformbasename 198 | fi 199 | 200 | # don't allow the sed command to completely eliminate the filename 201 | 202 | if [ x"$dstfile" = x ] 203 | then 204 | dstfile=`basename $dst` 205 | else 206 | true 207 | fi 208 | 209 | # Make a temp file name in the proper directory. 210 | 211 | dsttmp=$dstdir/#inst.$$# 212 | 213 | # Move or copy the file name to the temp name 214 | 215 | $doit $instcmd $src $dsttmp && 216 | 217 | trap "rm -f ${dsttmp}" 0 && 218 | 219 | # and set any options; do chmod last to preserve setuid bits 220 | 221 | # If any of these fail, we abort the whole thing. If we want to 222 | # ignore errors from any of these, just make sure not to ignore 223 | # errors from the above "$doit $instcmd $src $dsttmp" command. 224 | 225 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && 226 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && 227 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && 228 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && 229 | 230 | # Now rename the file to the real destination. 231 | 232 | $doit $rmcmd -f $dstdir/$dstfile && 233 | $doit $mvcmd $dsttmp $dstdir/$dstfile 234 | 235 | fi && 236 | 237 | 238 | exit 0 239 | -------------------------------------------------------------------------------- /interrupt.c: -------------------------------------------------------------------------------- 1 | /* Interrupt system emulation routines for kx10, the PDP-10 emulator. 2 | Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 3 | Stu Grossman 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 18 | 19 | #include "pdp10.h" 20 | #include 21 | 22 | /* 23 | Interrupts work as follows: 24 | 1) When a device wants to cause an interrupt, it calls set_interrupt() with 25 | a level number and a device-unique bit. This bit is then set in the 26 | request word for the specified interrupt level. 27 | 2) The 'interrupt' variable has one bit for each possible interrupt level. The 28 | level_mask variable is a ones complement mask of all the interrupt level 29 | bits for levels that are lower or equal to the priority of the current 30 | processor level. Ie: if the processor is running at level 4, then the mask 31 | will have bits 7, 6, 5, and 4 cleared. The disabled_mask variable is a 32 | ones complement mask of all levels which have been disabled via CONO PI,. 33 | So, the 'interrupt' variable is set by masking the indicated level number 34 | with level_mask and disabled_mask. 35 | 36 | The clear_interrupt() routine works similarly, but it doesn't need to take 37 | level_mask and disabled_mask into account, as it is simply clearing the 38 | appropriate bits. 39 | 40 | Using bit masks this way makes device emulation much easier, as the programmer 41 | can call set/clear_interrupt() without trying to match the number of calls to 42 | each. This also closely resembles the hardware model. 43 | 44 | Additionally, it will be pretty easy to recompute 'interrupt' whenever the 45 | CONO PI is changed, or an XJEN, or interrupt occurs. 46 | */ 47 | 48 | static volatile int request[8] = {0}; /* Bit map of requests for each level */ 49 | #if 0 50 | static int level_mask = ~0; /* Mask for current interrupt level */ 51 | static int disabled_mask = ~0; /* Mask of levels disabled by CONO PI, */ 52 | #endif 53 | 54 | void 55 | print_interrupts () 56 | { 57 | int i; 58 | 59 | if (interrupt != -1) 60 | { 61 | printf (", interrupt = %d", interrupt); 62 | 63 | for (i = 0; i <= 7; i++) 64 | if (request[i] != 0) 65 | printf (", request[%d] = 0x%x", i, request[i]); 66 | } 67 | } 68 | 69 | void 70 | calc_interrupt () 71 | { 72 | int level; 73 | 74 | if (request[0]) /* Level 0 is always on */ 75 | interrupt = 0; 76 | else 77 | { 78 | if (piconi & PISYSON) 79 | for (level = 1; level <= 7; level++) 80 | { 81 | if (piconi & 0100000 >> level) 82 | break; /* Already holding an interrupt at this level */ 83 | if (piconi & 0200 >> level /* Level on? */ 84 | && request[level]) 85 | { 86 | interrupt = level; 87 | return; 88 | } 89 | } 90 | interrupt = -1; 91 | } 92 | } 93 | 94 | static void 95 | print_sigprocmask () 96 | { 97 | sigset_t tmp; 98 | 99 | sigprocmask (SIG_BLOCK, NULL, &tmp); 100 | 101 | fprintf (stderr, "procmask = 0x%x\r\n", tmp); 102 | fflush (stderr); 103 | } 104 | 105 | /* Clear the highest interrupt level in preparation for doing a JEN/XJEN 106 | instruction. */ 107 | 108 | void 109 | finish_interrupt () 110 | { 111 | int level; 112 | sigset_t oldmask; 113 | 114 | sigprocmask (SIG_BLOCK, &blockedsigs, &oldmask); 115 | 116 | for (level = 1; level <= 7; level++) 117 | if (piconi & 0100000 >> level) 118 | { 119 | piconi &= ~0100000 >> level; /* Make this level inactive */ 120 | calc_interrupt(); 121 | break; 122 | } 123 | sigprocmask (SIG_SETMASK, &oldmask, NULL); 124 | } 125 | 126 | void 127 | handle_interrupt () 128 | { 129 | sigset_t oldmask; 130 | extern int rh0ivec; 131 | register int interrupt_tmp; 132 | 133 | interrupt_tmp = interrupt; 134 | 135 | if (interrupt_tmp == 0) 136 | { 137 | if (request[interrupt_tmp] & DTE_BIT) 138 | dte_interrupt (); 139 | else if (request[interrupt_tmp] & KNI_BIT) 140 | process_receive_packet (); 141 | } 142 | else if (interrupt_tmp > 0) /* Normal vectored interrupt */ 143 | { 144 | word36 ir; 145 | addr10 vector, ea; 146 | int opcode, ac; 147 | extern trace_ubr; 148 | 149 | #ifdef PROCESS_TRACING 150 | if (pagerdatailow == trace_ubr 151 | && pcflags & PC_USER) 152 | { 153 | printf ("Interrupt prior to pc %o\r\n", pcsection | pc); 154 | fflush (stdout); 155 | } 156 | #endif 157 | 158 | if (request[interrupt_tmp] & DTE_BIT) 159 | vector = 0142; 160 | else if (request[interrupt_tmp] & TIMER_BIT) 161 | vector = 0514; 162 | else if (request[interrupt_tmp] & RH0_BIT) 163 | vector = rh0ivec; 164 | else 165 | vector = 040 + 2 * interrupt_tmp; 166 | 167 | sigprocmask (SIG_BLOCK, &blockedsigs, &oldmask); 168 | piconi |= 0100000 >> interrupt_tmp; /* Make this level active */ 169 | calc_interrupt(); 170 | sigprocmask (SIG_SETMASK, &oldmask, NULL); 171 | 172 | nextvec: 173 | efetch (vector, &ir); 174 | opcode = ldb (8, 9, ir); 175 | ac = ldb (12, 4, ir); 176 | if (pcflags & PC_USER) 177 | goexec (); 178 | ea = ieacalc (ir, 0); /* Calc ea in section 0 */ 179 | 180 | if (opcode == 0254 && ac == 07) /* xpcw? */ 181 | { /* Yes. Use optimized inline code */ 182 | word36 flags, tmppc; 183 | 184 | dpb (17, 18, pcflags << 5, flags); 185 | dpb (35, 18, prev_pcsection >> 18, flags); 186 | vstore (ea, flags); 187 | 188 | dpb (5, 6, 0, tmppc); 189 | dpb (35, 30, pcsection | pc, tmppc); 190 | vstore (ea + 1, tmppc); 191 | 192 | vfetch (ea + 2, flags); 193 | 194 | vfetch (ea + 3, tmppc); 195 | 196 | prev_pcsection = ldb (35, 5, flags) << 18; 197 | pagerdataihigh = (pagerdataihigh & ~037) | (prev_pcsection >> 18); 198 | pcflags = ldb (12, 13, flags); 199 | 200 | setpc (ldb (35, 30, tmppc)); 201 | } 202 | else if ((opcode >= 0700 && (ac & 015) == 0) /* blki/blko */ 203 | || ((opcode & 0700) == 0600) /* txxx */ 204 | || ((opcode & 0710) == 0310)) /* camx, skipx, aosx, sosx (should add caix) */ 205 | { 206 | addr10 oldpc; 207 | 208 | /* Handle (most) skip instructions. If instruction skips, we dismiss 209 | the interrupt. If not, we execute the instruction in the vector 210 | location. */ 211 | 212 | oldpc = pc; 213 | (*opdisp[opcode]) (ac, ea); /* Recursively call the interpreter */ 214 | 215 | if (oldpc != pc) 216 | { /* It skipped. Dismiss the interrupt. */ 217 | pc = oldpc; 218 | 219 | if (pcflags & PC_USER) 220 | gouser (); 221 | finish_interrupt (); 222 | return; 223 | } 224 | 225 | /* Didn't skip. Take instruction from next loc. */ 226 | 227 | vector++; 228 | goto nextvec; 229 | } 230 | else if (opcode == 0265) /* jsp */ 231 | { 232 | dpb (12, 13, pcflags, AC); 233 | dpb (35, 23, pcsection|pc, AC); 234 | 235 | if (pcflags & PC_USER) 236 | pcflags &= PC_USER | PC_PUBLIC; 237 | 238 | setpc (ea); 239 | } 240 | else if (opcode == 0264) /* jsr */ 241 | { 242 | word36 tmp; 243 | 244 | tmp = zero36; 245 | 246 | if (pcsection) 247 | { 248 | dpb (35, 30, (pcsection | pc), tmp) /* 30 bit pc for non-zero sections */ 249 | } 250 | else 251 | { 252 | dpb (12, 13, pcflags, tmp); /* PC and flags for sect 0 */ 253 | dpb (35, 18, pc, tmp); 254 | } 255 | 256 | vstore (ea, tmp); /* Store current PC into (ea) */ 257 | 258 | if (pcflags & PC_USER) 259 | pcflags &= PC_USER | PC_PUBLIC; 260 | 261 | setpc (increa(ea)); /* Jump to ea+1 */ 262 | } 263 | else if (opcode == 0260 /* pushj */ 264 | || opcode == 0266) /* jsa */ 265 | { 266 | printf ("\r\nBad I/O instruction %o at vector %o, pc %o\r\n", opcode, vector, pc); 267 | genunimp (); 268 | } 269 | else 270 | { 271 | printf ("\r\nBad I/O instruction %o at vector %o, pc %o\r\n", opcode, vector, pc); 272 | genunimp (); /* All others undefined */ 273 | } 274 | 275 | return; 276 | } 277 | else 278 | { 279 | printf ("Got to handle_interrupt() without interrupt being set\r\n"); 280 | genunimp(); 281 | } 282 | } 283 | 284 | /* Call this routine to indicate that an interrupt is desired for the 285 | * specified device at the 286 | * specified level. When the interrupting condition has been satisfied, 287 | * clear_interrupt() must be called explicitly, as the simulated 288 | * interrupt system will not clear interrupts by itself. Failure to do 289 | * this will result in a hung system, which is constantly servicing 290 | * interrupts at the orphaned level. 291 | */ 292 | 293 | void 294 | set_interrupt(level, device_bit) 295 | int level; 296 | unsigned long device_bit; 297 | { 298 | sigset_t oldmask; 299 | 300 | sigprocmask (SIG_BLOCK, &blockedsigs, &oldmask); 301 | 302 | request[level & 07] |= device_bit; 303 | calc_interrupt(); 304 | 305 | sigprocmask (SIG_SETMASK, &oldmask, NULL); 306 | } 307 | 308 | /* Drop an interrupt request. This routine clears the device request for 309 | * the specified level. Additionally, it will clear out the level request 310 | * if that level is now free. 311 | */ 312 | 313 | void 314 | clear_interrupt(level, device_bit) 315 | int level; 316 | unsigned long device_bit; 317 | { 318 | sigset_t oldmask; 319 | 320 | sigprocmask (SIG_BLOCK, &blockedsigs, &oldmask); 321 | 322 | request[level & 07] &= ~device_bit; 323 | calc_interrupt(); 324 | 325 | sigprocmask (SIG_SETMASK, &oldmask, NULL); 326 | } 327 | -------------------------------------------------------------------------------- /kx10.c: -------------------------------------------------------------------------------- 1 | /* Main emulator loop for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | /* The main emulator !!! */ 19 | 20 | #include "pdp10.h" 21 | #include 22 | #include 23 | #include 24 | 25 | #if 0 26 | word36 zero36 = {0,0}; 27 | word36 one36 = {0777777,0777777}; 28 | #else 29 | word36 zero36; 30 | word36 one36; 31 | #endif 32 | 33 | addr10 pchist[1024]; /* PC history buffer */ 34 | int pchp = 0; /* Pointer into pchist */ 35 | int debug_monitor; /* > 0 means to debug kernel */ 36 | int patch_monitor = 1; /* != 0 means install dte patches */ 37 | int waits_flag = 0; /* != 0 means booting a Waits .dmp file */ 38 | int icount, intcount; 39 | int boot_flags = 0; 40 | 41 | addr10 pc_cache_vm; 42 | 43 | /*static int __main () {return 0;}*/ 44 | 45 | /* Setup the processor, resets the 'pager' and the channels, etc... */ 46 | 47 | void 48 | processor_initialize() 49 | { 50 | currentacblock = acfile; /* Reset to ac block 0 */ 51 | prevacblock = acfile; 52 | mem_acblock = currentacblock; 53 | mem_acblock_1 = currentacblock; 54 | mem_acblock_2 = currentacblock; 55 | ea_acblock = currentacblock; 56 | 57 | pager_init (); /* Clear tlbs, setup for exec VM accesses */ 58 | 59 | interrupt = -1; 60 | 61 | io_init(); /* Setup I/O devices */ 62 | 63 | console_init(); 64 | } 65 | 66 | static void 67 | handle_fpe () 68 | { 69 | printf("\r\nSIGFPE\r\n"); 70 | genunimp (); 71 | } 72 | 73 | #ifdef PC_PROFILE 74 | static unsigned long pccount = 0; 75 | static unsigned long misscount = 0; 76 | 77 | void 78 | print_pccounts () 79 | { 80 | printf ("pccount = %d, misscount = %d, hit percentage %g", 81 | pccount, misscount, ((double)pccount - misscount)/pccount); 82 | printf ("\r\n"); 83 | } 84 | #endif /* PC_PROFILE */ 85 | 86 | #if 0 87 | int 88 | set_cry0() 89 | { 90 | if (!(pcflags & 04000)) 91 | printf ("S:%o ", pc); 92 | 93 | return 04000; 94 | } 95 | 96 | int 97 | set_cry1() 98 | { 99 | /* printf ("S:%o ", pc);*/ 100 | 101 | return 02000; 102 | } 103 | #endif 104 | 105 | void 106 | execute(start_address) 107 | addr10 start_address; 108 | { 109 | register addr10 ea; /* Effective address */ 110 | register int opcode; 111 | word36 ir; 112 | 113 | processor_initialize(); 114 | 115 | if (boot_flags) 116 | { 117 | dpb (17, 18, 0400000, acref(0)); /* No prompting */ 118 | dpb (35, 18, 0, acref(0)); 119 | start_address++; 120 | } 121 | 122 | #if 1 123 | /* The following crock fools TOPS-20 into thinking that there is a 1 page 124 | copy of the boot code at the top of section 0. Without this ruse, the 125 | monitor gets very confused. */ 126 | 127 | dpb(17, 18, -1, ir); 128 | dpb(35, 18, 0777000, ir); 129 | pstore(0204, ir); 130 | #endif 131 | 132 | if (patch_monitor != 0) 133 | { 134 | jam_input ("proflg[0\r"); 135 | jam_input ("dteq[ret\r"); 136 | } 137 | 138 | if (!waits_flag && debug_monitor > 0) 139 | { 140 | jam_input ("1\0331m"); 141 | jam_input ("stg\033:"); 142 | jam_input ("dbugsw[2\r"); 143 | jam_input ("eddtf[1\r"); 144 | } 145 | 146 | #ifdef PCHIST 147 | opdisp[0777] = i_trace; 148 | #endif 149 | #ifdef PROCESS_TRACING 150 | opdisp[0777] = i_trace; 151 | #endif 152 | 153 | signal (SIGFPE, handle_fpe); 154 | 155 | pcsection = 0; 156 | 157 | pc = start_address; 158 | 159 | /* siglongjmp to here when we need to abort the current instruction. This is 160 | usually done for page faults, but can also occur in xct loops, or EA calc 161 | loops. */ 162 | sigsetjmp (to_main, 0); 163 | 164 | while (1) 165 | { 166 | extern int trace_ubr; 167 | addr10 pctmp; 168 | word36 *pc_cache_mapping; 169 | 170 | if (interrupt >= 0) 171 | { 172 | /* intcount++;*/ 173 | handle_interrupt(); 174 | } 175 | /* icount++;*/ 176 | 177 | #ifdef PCHIST 178 | #if 0 179 | if (pcflags & PC_USER) 180 | #endif 181 | pchist[pchp++ % 1024] = pcflags << 23 | pcsection | pc; 182 | 183 | #if 1 184 | if (pc < 020) 185 | genunimp (); 186 | #endif 187 | #if 0 188 | if (pc == 0572622) { 189 | printf("Got to here\r\n"); 190 | /* genunimp();*/ 191 | } 192 | #endif /* undef */ 193 | #endif /* PCHIST */ 194 | 195 | #if 0 196 | if ((pcflags & PC_USER) 197 | && (pc == 0505672) 198 | && (pcsection == 01000000)) 199 | printf ("Got to here\r\n"); 200 | #endif 201 | 202 | /* 203 | Note that all PC refs are implicitly LOCAL. This causes the PC to wrap 204 | around at section boundaries. It also means that PC refs to 0-17 in any 205 | section really refer to the ACs. 206 | */ 207 | 208 | #if 1 209 | #ifdef PC_PROFILE 210 | pccount++; 211 | #endif 212 | pctmp = pcsection | pc; 213 | if (pctmp & 0777760) 214 | { 215 | if ((pctmp & KLPAGEMASK) != pc_cache_vm) 216 | { 217 | #ifdef PC_PROFILE 218 | misscount++; 219 | #endif 220 | pc_cache_mapping = vfetch_i_ref (pctmp); 221 | pc_cache_vm = pctmp & KLPAGEMASK; 222 | } 223 | 224 | ir = *(pc_cache_mapping + pctmp); 225 | } 226 | else 227 | ir = mem_acref (pctmp); 228 | #else 229 | vfetch_i (pcsection | pc, ir); 230 | #endif 231 | 232 | #ifdef PROCESS_TRACING 233 | if (pagerdatailow == trace_ubr 234 | && pcflags & PC_USER) 235 | { 236 | printf ("%o: ", pcsection | pc); 237 | print_instruction (ir); 238 | } 239 | #endif 240 | 241 | incrpc; 242 | 243 | ea = ieacalc(ir, pcsection); 244 | 245 | opcode = ldb(8, 9, ir); 246 | (*opdisp[opcode])(ldb(12, 4, ir), ea); 247 | } 248 | } 249 | 250 | int 251 | main (argc, argv) 252 | int argc; 253 | char *argv[]; 254 | { 255 | addr10 entvec; 256 | char *sysname; 257 | extern int tops10_paging; 258 | 259 | cfg = ConfigFileOpen ("kx10.config"); 260 | 261 | output_version (); 262 | 263 | #if 1 264 | zero36.hi = 0; 265 | zero36.lo = 0; 266 | one36.hi = 0777777; 267 | one36.lo = 0777777; 268 | #endif 269 | 270 | /* memarray = (word36 *)calloc(2000000, sizeof(word36));*/ 271 | 272 | entvec = -1; 273 | 274 | argc--; 275 | argv++; 276 | 277 | for (;argc > 0; argc--, argv++) 278 | if (argv[0][0] == '-') 279 | switch (argv[0][1]) 280 | { 281 | case 'b': /* non-dialog (boot.exe) */ 282 | boot_flags = 1; 283 | break; 284 | case 'd': 285 | debug_monitor++; 286 | break; 287 | case 'n': 288 | patch_monitor = 0; 289 | debug_monitor = 0; 290 | break; 291 | case 'w': 292 | waits_flag = 1; 293 | patch_monitor = 0; 294 | break; 295 | case 't': 296 | tops10_paging = 1; 297 | break; 298 | default: 299 | fprintf (stderr, "Usage: kx10 [-b] [-d] [-n] [-w] [executable ...]\n"); 300 | exit (1); 301 | } 302 | else 303 | entvec = readexe (*argv); 304 | 305 | if (entvec == -1) 306 | readexe ("monitr.exe"); 307 | 308 | if (!waits_flag && (debug_monitor || patch_monitor)) 309 | entvec = (addr10)0142; /* Start address of EDDT */ 310 | 311 | { 312 | int val; 313 | 314 | fprintf (stderr, "[Locking down memarray, %d bytes]\n", sizeof memarray); 315 | 316 | val = mlock ((caddr_t) memarray, sizeof memarray); 317 | if (val) 318 | fprintf (stderr, "[Failed to lock down memarray, errno = %d]\n", errno); 319 | } 320 | 321 | fprintf (stderr, "[Starting at 0%o]\n", entvec); 322 | execute (entvec); 323 | 324 | return 0; /* Never actually gets here */ 325 | } 326 | -------------------------------------------------------------------------------- /loadexe.c: -------------------------------------------------------------------------------- 1 | /* Executable loading routines for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | /* Loadup executables into pseudo-core. */ 19 | 20 | #include "pdp10.h" 21 | #include 22 | 23 | static addr10 readexb PARAMS ((void)); 24 | 25 | static addr10 readdmp PARAMS ((void)); 26 | 27 | FILE *exefd; 28 | 29 | /* Read a 36 bit word from exefd */ 30 | 31 | static word36 32 | get36() 33 | { 34 | word36 thisword; 35 | unsigned char buf[5]; 36 | 37 | if (fread(buf, 5, 1, exefd) != 1) { 38 | printf("Got an error from fread\n"); 39 | exit(1); 40 | } 41 | 42 | string_to_word36(buf, thisword); 43 | 44 | return(thisword); 45 | } 46 | 47 | /* Read pages from the .EXE file into memory */ 48 | 49 | static void 50 | load_pages(from, xto, count) 51 | register unsigned long from, xto; 52 | register unsigned long count; 53 | { 54 | register word36 curword; 55 | 56 | count <<= 9; /* Now it's a word count */ 57 | from <<= 9; 58 | xto <<= 9; 59 | 60 | if (from) { /* Non-zero page. Copy contents */ 61 | long curpos; 62 | 63 | curpos = ftell(exefd); 64 | fseek(exefd, from * 5, 0); 65 | 66 | while(count-- > 0) { 67 | curword = get36(); 68 | pstore(xto, curword); 69 | xto++; 70 | } 71 | fseek(exefd, curpos, 0); 72 | } else { /* Zero fill page */ 73 | curword = zero36; 74 | while(count-- > 0) { 75 | pstore(xto, curword); 76 | xto++; 77 | } 78 | } 79 | 80 | } 81 | 82 | static int geta10num PARAMS ((int *termchar)); 83 | 84 | static int linenum; 85 | 86 | static int 87 | geta10num (termchar) 88 | int *termchar; 89 | { 90 | int num; 91 | int c; 92 | int i; 93 | 94 | num = 0; 95 | 96 | for (i = 1; i <= 4; i++) 97 | { 98 | c = getc (exefd); 99 | switch (c) 100 | { 101 | case '\r': 102 | continue; 103 | case '\n': 104 | linenum++; 105 | case ',': 106 | case EOF: 107 | if (num > 0177777) 108 | { 109 | fprintf (stderr, "geta10num: Badly formatted number at line %d.\n", linenum); 110 | exit (1); 111 | } 112 | *termchar = c; 113 | return num; 114 | default: 115 | num = (num << 6) | (c & 077); 116 | } 117 | } 118 | fprintf (stderr, "geta10num: Number too long at line %d.\n", linenum); 119 | exit (1); 120 | } 121 | 122 | static int 123 | geta10line (numbufp) 124 | int *numbufp; 125 | { 126 | int num; 127 | int checksum; 128 | 129 | num = 0; 130 | checksum = 0; 131 | while (1) 132 | { 133 | int term; 134 | int x; 135 | 136 | x = geta10num (&term); 137 | checksum += x; 138 | *numbufp++ = x; 139 | num++; 140 | 141 | if (term != ',') 142 | break; 143 | } 144 | 145 | if ((checksum & 0177777) == 0) 146 | return num; 147 | 148 | fprintf (stderr, "Bad checksum at line %d.\n", linenum); 149 | exit (1); 150 | } 151 | 152 | /* Read an A10 file. This is similar to a uuencoded file, but with checksums 153 | and a few more bells and whistles for zeroing and loading memory. */ 154 | 155 | static addr10 156 | reada10 () 157 | { 158 | int linetype; 159 | int num; 160 | int numbuf[100]; 161 | int *numbufp; 162 | int cnt; 163 | addr10 addr, lastaddr, firstaddr; 164 | 165 | firstaddr = -1; 166 | lastaddr = -1; 167 | linenum = 1; 168 | 169 | while (1) 170 | { 171 | int c; 172 | 173 | numbufp = numbuf; 174 | /* First char of line */ 175 | c = getc (exefd); 176 | switch (c) 177 | { 178 | case ';': /* Comment. Ignore rest of line */ 179 | do 180 | c = getc (exefd); 181 | while (c != '\n' && c != EOF); 182 | if (c == EOF) 183 | break; 184 | continue; 185 | case 'T': 186 | case 'Z': 187 | linetype = c; 188 | 189 | c = getc (exefd); 190 | 191 | if (c != ' ') 192 | fprintf (stderr, "Bad line format %c\n", c); 193 | 194 | num = geta10line (numbuf); 195 | 196 | cnt = numbuf[0] & 0377; /* # of 16 bit words */ 197 | addr = numbuf[1] | ((numbuf[0] << 2) & 0600000); /* -10 address */ 198 | numbufp = numbuf + 2; 199 | 200 | if (linetype == 'Z') /* Zero memory */ 201 | while (cnt-- > 0) 202 | { 203 | int wrdcnt; 204 | 205 | wrdcnt = *numbufp++; 206 | fprintf (stderr, "[Zeroing memory from 0%o to 0%o]\n", addr, 207 | addr + wrdcnt - 1); 208 | while (wrdcnt--) 209 | { 210 | pstore (addr, zero36); 211 | addr++; 212 | } 213 | } 214 | else /* Load memory */ 215 | if (cnt == 0) /* Start address */ 216 | return addr; 217 | else 218 | { 219 | if (addr != lastaddr) 220 | { 221 | if (lastaddr != -1) 222 | if (lastaddr == firstaddr + 1) 223 | fprintf (stderr, "[Loading memory at 0%o]\n", firstaddr); 224 | else 225 | fprintf (stderr, "[Loading memory from 0%o to 0%o]\n", firstaddr, 226 | lastaddr - 1); 227 | firstaddr = addr; 228 | } 229 | 230 | for (; cnt > 0; cnt -= 3) 231 | { 232 | word36 mem; 233 | int tmp; 234 | 235 | tmp = *numbufp++; 236 | dpb (35, 16, tmp, mem); 237 | 238 | tmp = *numbufp++; 239 | dpb (19, 16, tmp, mem); 240 | 241 | tmp = *numbufp++; 242 | dpb (3, 4, tmp, mem); 243 | 244 | pstore (addr, mem); 245 | addr++; 246 | } 247 | lastaddr = addr; 248 | } 249 | continue; 250 | default: /* Not a T, Z, or ; */ 251 | fprintf (stderr, "reada10: Unknown line type `%c'.\n", c); 252 | exit (1); 253 | } 254 | break; 255 | } 256 | } 257 | 258 | /* Read an .EXE file. First part is the directory. This directory tells us where all the 259 | * bits go into memory. Returns the address of the entry vector. 260 | */ 261 | 262 | addr10 263 | readexe (exefilename) 264 | char *exefilename; 265 | { 266 | word36 curword; 267 | int numwordsindir, blocktype; 268 | addr10 entryvector; 269 | extern int waits_flag; 270 | char *p; 271 | 272 | exefd = fopen (exefilename, "r"); 273 | if (!exefd) 274 | { 275 | fprintf (stderr, "? File %s does not exist or is not readable\n", 276 | exefilename); 277 | exit (1); 278 | } 279 | 280 | p = strrchr (exefilename, '.'); 281 | 282 | if (p && strcmp (p, ".a10") == 0) 283 | return reada10 (); 284 | 285 | if (waits_flag) 286 | return readdmp (); 287 | 288 | curword = get36 (); 289 | if (upper18 (curword) != 01776) 290 | return readexb (); /* Not an exe file, try exb file */ 291 | 292 | printf ("File\tMem\tCount\tFlags\n"); 293 | 294 | while (1) 295 | { 296 | blocktype = upper18 (curword); 297 | numwordsindir = lower18 (curword) - 1; 298 | 299 | switch (blocktype) 300 | { 301 | case 01776: /* page map */ 302 | for (; numwordsindir > 0; numwordsindir -= 2) 303 | { 304 | unsigned filepage, procpage; 305 | unsigned pagecount, flags; 306 | 307 | curword = get36 (); 308 | filepage = ldb (35, 27, curword); 309 | flags = ldb (8, 9, curword); 310 | 311 | curword = get36 (); 312 | procpage = ldb (35, 27, curword); 313 | pagecount = ldb (8, 9, curword) + 1; 314 | 315 | printf ("%o\t%o\t%d\t%o\n", filepage, procpage, pagecount, flags); 316 | 317 | load_pages (filepage, procpage, pagecount); 318 | } 319 | break; 320 | case 01775: /* Entry vector location */ 321 | curword = get36 (); /* Get entry vector length */ 322 | blocktype = ldb (35, 32, curword); 323 | if (ldb (35, 32, curword) > 0) 324 | { 325 | curword = get36 (); 326 | entryvector = ldb (35, 32, curword); 327 | printf ("entryvector=%012o\n", entryvector); 328 | 329 | return (entryvector); 330 | } 331 | break; 332 | case 01774: 333 | while (numwordsindir--) 334 | get36 (); 335 | break; 336 | case 01777: 337 | return (entryvector); 338 | default: 339 | printf ("Illegal .EXE directory, bad blocktype\n"); 340 | exit (1); 341 | } 342 | curword = get36 (); 343 | } 344 | } 345 | 346 | /* Read an EXB (RSX boot image) file */ 347 | 348 | static int get8 PARAMS ((void)); 349 | 350 | static int 351 | get8 () 352 | { 353 | static int pos = -1; 354 | static word36 curword; 355 | 356 | pos++; 357 | 358 | switch (pos & 3) 359 | { 360 | case 0: 361 | curword = get36 (); 362 | return ldb (17, 8, curword); 363 | case 1: 364 | return ldb (9, 8, curword); 365 | case 2: 366 | return ldb (35, 8, curword); 367 | case 3: 368 | return ldb (27, 8, curword); 369 | } 370 | } 371 | 372 | static addr10 373 | readexb () 374 | { 375 | int odd = 0; 376 | 377 | fseek (exefd, 0, SEEK_SET); 378 | 379 | while (1) 380 | { 381 | int numbytes; 382 | addr10 addr; 383 | int biw = 0; 384 | int trash; 385 | 386 | if (odd) 387 | trash = get8 (); 388 | 389 | /* Count includes # of bytes of 36 bit word info + 4 390 | for address. */ 391 | 392 | numbytes = get8 (); 393 | numbytes |= get8 () << 8; 394 | numbytes -= 4; 395 | odd = numbytes & 1; 396 | 397 | addr = get8 (); 398 | addr |= get8 () << 8; 399 | addr |= get8 () << 16; 400 | addr |= get8 () << 24; 401 | 402 | if (numbytes == 0) 403 | return addr; /* start address */ 404 | 405 | for (; numbytes > 0; numbytes--, biw++) 406 | { 407 | int curbyt; 408 | 409 | curbyt = get8 (); 410 | 411 | switch (biw) 412 | { 413 | case 0: 414 | dpb (35, 8, curbyt, memarray[addr]); 415 | break; 416 | case 1: 417 | dpb (27, 8, curbyt, memarray[addr]); 418 | break; 419 | case 2: 420 | dpb (19, 8, curbyt, memarray[addr]); 421 | break; 422 | case 3: 423 | dpb (11, 8, curbyt, memarray[addr]); 424 | break; 425 | case 4: 426 | dpb (3, 4, curbyt, memarray[addr]); 427 | addr++; 428 | biw = -1; 429 | break; 430 | } 431 | } 432 | } 433 | } 434 | 435 | /* Read a Waits dmp file */ 436 | 437 | static addr10 438 | readdmp () 439 | { 440 | unsigned char buf[5]; 441 | addr10 addr = 074; 442 | word36 mem; 443 | extern int debug_monitor; 444 | 445 | while (1) 446 | { 447 | if (fread(buf, 5, 1, exefd) != 1) 448 | { 449 | if (feof (exefd)) 450 | break; 451 | 452 | printf("Got an error from fread\n"); 453 | exit(1); 454 | } 455 | string_to_word36(buf, memarray[addr]); 456 | addr++; 457 | } 458 | 459 | printf ("[Highest addr = 0%o]\r\n", addr - 1); 460 | 461 | pfetch (0116, mem); /* Get .jbsym */ 462 | pstore (036, mem); /* Put it where eddt expects it */ 463 | 464 | pstore (037, one36); /* Fake out jobrel */ 465 | 466 | if (!debug_monitor) 467 | pfetch (0120, mem); /* Get jobsa */ 468 | else 469 | pfetch (074, mem); /* Get jobddt */ 470 | 471 | addr = lower18 (mem); /* Get start address */ 472 | 473 | return addr; 474 | } 475 | -------------------------------------------------------------------------------- /misc.c: -------------------------------------------------------------------------------- 1 | /* Utility routines for kx10, the PDP-10 emulator. 2 | Copyright (C) 1991, 1992, 1993, 1994, 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | 20 | void 21 | print_instruction (ir) 22 | word36 ir; 23 | { 24 | static char *iocodes[] = {"blki", "datai", "blko", "datao", "cono", 25 | "coni", "consz", "conso"}; 26 | static char *iodevs[] = {"apr", "pi", "pag", "cca", "tim", "mtr"}; 27 | static char *extends[] = {"0", "cmpsl", "cmpse", "cmpsle", "edit", "cmpsge", 28 | "cmpsn", "cmpsg", 29 | "cvtdbo", "cvtdbt", "cvtbdo", "cvtbdt", 30 | "movso", "movst", "movslj", "movsrj", 31 | "xblt", 32 | "gsngl", "gdble", "gdfix", "gfix", "gdfixr", 33 | "gfixr", "dgfltr", "gfltr", "gfsc"}; 34 | extern char *opnames[]; 35 | int opcode, ac; 36 | int dev; 37 | 38 | opcode = ldb (8, 9, ir); 39 | ac = ldb (12, 4, ir); 40 | 41 | if (opcode >= 0700) 42 | { /* I/O instruction */ 43 | dev = ((opcode << 1) | (ac >> 3)) & 0177; 44 | 45 | printf("%s ", iocodes[ac & 7]); 46 | 47 | if (dev > 5) 48 | printf("%o", dev << 2); 49 | else 50 | printf("%s", iodevs[dev]); 51 | } 52 | else 53 | { /* Normal instruction */ 54 | printf("%s ", opnames[opcode]); 55 | if (ac) 56 | printf("%o,", ac); 57 | } 58 | 59 | if (ldb (13, 1, ir)) /* Deal with I and Y */ 60 | putchar ('@'); 61 | if (lower18 (ir) != 0) 62 | printf ("%o", lower18 (ir)); 63 | 64 | if (ldb (17, 4, ir)) /* X (index) */ 65 | printf ("(%lo)\r\n", ldb (17, 4, ir)); 66 | else 67 | printf ("\r\n"); 68 | } 69 | 70 | void 71 | xneg36 (dst, src) 72 | word36 *dst; 73 | word36 src; 74 | { 75 | if (upper18(src) == 0400000 76 | && lower18(src) == 0) 77 | printf ("neg36 trying to negate setz %o,,%o\r\n", (pcflags << 5)|(pcsection >> 18), pc); 78 | 79 | not36(*dst, src); 80 | incr36(*dst); 81 | } 82 | 83 | /* Print out a 72 bit quantity */ 84 | 85 | void 86 | print72 (dword1, dword2) 87 | word36 dword1, dword2; 88 | { 89 | printf ("%06o,%06o,%06o,%06o", upper18 (dword1), lower18 (dword1), 90 | upper18 (dword2), lower18 (dword2)); 91 | } 92 | 93 | /* Print out a 36 bit word as octal halfwords */ 94 | 95 | void 96 | print36(word) 97 | word36 word; 98 | { 99 | printf("%06o,,%06o", upper18(word), lower18(word)); 100 | } 101 | 102 | void 103 | pa(ac) 104 | int ac; 105 | { 106 | print36(acref(ac)); 107 | } 108 | 109 | #ifdef PROCESS_TRACING 110 | int trace_ubr; 111 | #endif 112 | 113 | void 114 | i_trace (opcode, ac, ea) 115 | int opcode; 116 | int ac; 117 | addr10 ea; 118 | { 119 | #ifdef PCHIST 120 | ppc (); 121 | i_uuo (opcode, ac, ea); 122 | #else 123 | # ifdef PROCESS_TRACING 124 | if (!trace_ubr) 125 | { 126 | trace_ubr = pagerdatailow; 127 | printf ("[kx10: instruction tracing ON]\r\n"); 128 | } 129 | else 130 | { 131 | trace_ubr = 0; 132 | printf ("[kx10: Turning OFF instruction tracing]\r\n"); 133 | } 134 | fflush (stdout); 135 | # else /* PROCESS_TRACING */ 136 | i_uuo (opcode, ac, ea); 137 | # endif 138 | #endif 139 | } 140 | 141 | /* ppc() - Print out PC history buffer, and dump stack also */ 142 | 143 | void 144 | ppc () 145 | { 146 | int i; 147 | word36 mem; 148 | addr10 addr; 149 | extern addr10 pchist[]; 150 | extern int pchp; 151 | int count; 152 | 153 | printf("\r\n"); 154 | 155 | /* Dump accumulators */ 156 | 157 | for (i=0; i<=15; i++) { 158 | pa(i); 159 | printf(" "); 160 | } 161 | printf("\r\n"); 162 | 163 | #ifdef PCHIST 164 | /* Dump PC history */ 165 | 166 | for(i = 1; i <= 100; i++) printf("%06o ", pchist[(pchp - i) % 1024]); 167 | printf("\r\n"); 168 | #endif /* PCHIST */ 169 | 170 | #if 0 171 | /* Dump stack */ 172 | 173 | count = upper18(acref(017)); 174 | if (pcsection && count <= 0377777 && count != 0) 175 | addr = ldb(35, 30, acref(017)); /* Get 30 bit stack addr from ac */ 176 | else 177 | addr = pcsection | ldb(35, 18, acref(017)); /* Local stack pointer */ 178 | 179 | for(i = 1; i <= 100; i++) 180 | { 181 | vfetch(addr, mem); 182 | addr--; 183 | print36(mem); 184 | printf(" "); 185 | } 186 | #endif 187 | 188 | printf("\r\n"); 189 | fflush(stdout); 190 | } 191 | 192 | /* Print out a 36 bit memory location */ 193 | 194 | void 195 | pl36(ea) 196 | addr10 ea; 197 | { 198 | word36 tmp; 199 | 200 | vfetch(ea, tmp); 201 | 202 | printf("%06o,,%06o\n", upper18(tmp), lower18(tmp)); 203 | } 204 | -------------------------------------------------------------------------------- /monitr.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brouhaha/kx10/6f4f55267176727dc3c34ff60a269fe6dab22a7c/monitr.exe -------------------------------------------------------------------------------- /readconfig.c: -------------------------------------------------------------------------------- 1 | /* Config file reader for kx10, the PDP-10 emulator. 2 | Copyright (C) 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | /* Size of the constant part of Config_t */ 31 | #define configsize (sizeof (struct _config) - 1) 32 | 33 | Config_t 34 | ConfigFileOpen (filename) 35 | const char *filename; 36 | { 37 | FILE *f; 38 | Config_t configinfo; 39 | long len; 40 | 41 | f = fopen (filename, "r"); 42 | 43 | if (!f) 44 | return NULL; 45 | 46 | fseek (f, 0, 2); /* Go to end of file */ 47 | len = ftell (f); /* Get the length of the file */ 48 | fseek (f, 0, 0); /* Back to the beginning */ 49 | 50 | configinfo = malloc (configsize + len + 1); 51 | fread (configinfo->data, 1, len, f); 52 | configinfo->data[len] = '\000'; /* Tie it off with a NUL */ 53 | configinfo->len = len; 54 | 55 | return configinfo; 56 | } 57 | 58 | /* Lookup NAME in CONFIG, starting at PPTR. Returns a pointer to the start of 59 | the value associated with NAME. The pointer at PPTR (if not NULL) is 60 | adjusted to point to the next line of the config file. */ 61 | 62 | static char * 63 | lookupval (configinfo, pptr, name) 64 | const Config_t configinfo; 65 | Config_ptr *pptr; 66 | const char *name; 67 | { 68 | char *ptr; 69 | char *endptr; 70 | int namelen; 71 | char *val; 72 | 73 | if (!configinfo) 74 | return NULL; 75 | 76 | namelen = strlen (name); 77 | 78 | endptr = configinfo->data + configinfo->len; 79 | 80 | if (pptr) 81 | { 82 | if (*pptr >= endptr) 83 | return NULL; 84 | 85 | ptr = *pptr; 86 | } 87 | else 88 | ptr = configinfo->data; 89 | 90 | while (ptr < endptr) 91 | { 92 | /* We should now be at the start of a line */ 93 | 94 | /* Skip leading whitespace */ 95 | while (*ptr == ' ' || *ptr == '\t') 96 | ptr++; 97 | 98 | if ((ptr[namelen] == ' ' 99 | || ptr[namelen] == '\t') 100 | && strncasecmp (name, ptr, namelen) == 0) 101 | { /* Found name */ 102 | /* Skip whitespace between name and value */ 103 | ptr += namelen + 1; 104 | while (*ptr == ' ' || *ptr == '\t') 105 | ptr++; 106 | 107 | val = ptr; 108 | 109 | /* Find end of value */ 110 | while (*ptr != '\n' 111 | && *ptr != '\000') 112 | ptr++; 113 | *ptr++ = '\000'; /* Tie off value */ 114 | if (pptr) 115 | *pptr = ptr; 116 | return val; 117 | } 118 | else 119 | { /* Didn't find name */ 120 | /* Skip this line (which might end with a NUL) */ 121 | while (*ptr != '\n' 122 | && *ptr != '\000') 123 | ptr++; 124 | ptr++; /* Skip end of line char */ 125 | } 126 | } 127 | return NULL; 128 | } 129 | 130 | char * 131 | ConfigGetString (configinfo, pptr, name) 132 | const Config_t configinfo; 133 | Config_ptr *pptr; 134 | const char *name; 135 | { 136 | char *p; 137 | 138 | p = lookupval (configinfo, pptr, name); 139 | 140 | return p; 141 | } 142 | 143 | struct ether_addr * 144 | ConfigGetEthernetAddress (configinfo, pptr, name) 145 | const Config_t configinfo; 146 | Config_ptr *pptr; 147 | const char *name; 148 | { 149 | char *p; 150 | /* extern struct ether_addr *ether_aton PARAMS ((char *s));*/ 151 | 152 | p = lookupval (configinfo, pptr, name); 153 | 154 | if (!p) 155 | return NULL; 156 | 157 | return ether_aton (p); 158 | } 159 | 160 | char * 161 | ConfigGetHostAddress (configinfo, pptr, name) 162 | const Config_t configinfo; 163 | Config_ptr *pptr; 164 | const char *name; 165 | { 166 | char *p; 167 | struct hostent *he; 168 | 169 | p = lookupval (configinfo, pptr, name); 170 | 171 | if (!p) 172 | return NULL; 173 | 174 | he = gethostbyname (p); 175 | 176 | if (!he) 177 | return NULL; 178 | 179 | return he->h_addr_list[0]; 180 | } 181 | -------------------------------------------------------------------------------- /unpack.c: -------------------------------------------------------------------------------- 1 | /* High density => core dump format converter program for kx10, the PDP-10 emulator. 2 | Copyright (C) 1994 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | /* Unpack 4.5 bytes/word to 5 bytes per word */ 19 | 20 | #include 21 | 22 | main() 23 | { 24 | unsigned char ibuf[9]; 25 | unsigned char obuf[10]; 26 | 27 | while (1) 28 | { 29 | int i; 30 | 31 | i = fread (ibuf, 1, 9, stdin); 32 | if (i != 9 && i != 5) 33 | { 34 | if (i != 0) 35 | { 36 | fprintf (stderr, "Not multiple of 9 or 5 bytes!\n"); 37 | exit(1); 38 | } 39 | exit(0); 40 | } 41 | obuf[0] = ibuf[0]; 42 | obuf[1] = ibuf[1]; 43 | obuf[2] = ibuf[2]; 44 | obuf[3] = ibuf[3]; 45 | obuf[4] = ibuf[4] >> 4; 46 | 47 | obuf[5] = (ibuf[4] & 017) << 4 | (ibuf[5] >> 4); 48 | obuf[6] = (ibuf[5] & 017) << 4 | (ibuf[6] >> 4); 49 | obuf[7] = (ibuf[6] & 017) << 4 | (ibuf[7] >> 4); 50 | obuf[8] = (ibuf[7] & 017) << 4 | (ibuf[8] >> 4); 51 | obuf[9] = ibuf[8] & 017; 52 | if (i == 9) 53 | fwrite (obuf, 1, 10, stdout); 54 | else 55 | fwrite (obuf, 1, 5, stdout); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /version.c: -------------------------------------------------------------------------------- 1 | /* Version output routines for kx10, the PDP-10 emulator. 2 | Copyright (C) 1994, 1995 Stu Grossman 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 17 | 18 | #include "pdp10.h" 19 | 20 | void 21 | output_version () 22 | { 23 | printf ("kx10 version 0.95, Copyright (C) 1994, 1995, 1996 Stu Grossman\n\ 24 | kx10 comes with ABSOLUTELY NO WARRANTY; for details look at COPYING.\n\ 25 | This is free software, and you are welcome to redistribute it\n\ 26 | under certain conditions; look at COPYING for details.\n"); 27 | } 28 | --------------------------------------------------------------------------------