├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENCE.txt ├── README.md ├── common ├── instruction.h ├── opcode.c └── opcode.h ├── disassembler ├── disassembler.c ├── disassembler.h ├── main.c ├── opcode.c └── opcode.h └── interpreter ├── clown68000.c ├── clown68000.h ├── microcode-generator ├── emit-instructions.c ├── emit-instructions.h ├── emit.c ├── emit.h ├── generator.c ├── instruction-properties.c └── instruction-properties.h ├── microcode.c └── unity.c /.gitignore: -------------------------------------------------------------------------------- 1 | # CMake build directory. 2 | /build 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "clowncommon"] 2 | path = common/clowncommon 3 | url = https://github.com/Clownacy/clowncommon 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0...3.12) 2 | 3 | option(CC_USE_C99_INTEGERS "Use C99 integer types instead of the original C89 ones. May save RAM depending on the platform's data model." OFF) 4 | 5 | project(clown68000 LANGUAGES C) 6 | 7 | # Common 8 | 9 | add_library(clown68000-common STATIC 10 | "common/clowncommon/clowncommon.h" 11 | "common/instruction.h" 12 | "common/opcode.c" 13 | "common/opcode.h" 14 | ) 15 | 16 | set_target_properties(clown68000-common PROPERTIES 17 | C_STANDARD 90 18 | C_STANDARD_REQUIRED OFF 19 | C_EXTENSIONS OFF 20 | ) 21 | 22 | if(CC_USE_C99_INTEGERS) 23 | target_compile_definitions(clown68000-common PUBLIC CC_USE_C99_INTEGERS) 24 | endif() 25 | 26 | # Interpreter 27 | 28 | add_library(clown68000-interpreter STATIC 29 | "interpreter/clown68000.c" 30 | "interpreter/clown68000.h" 31 | ) 32 | 33 | target_link_libraries(clown68000-interpreter PRIVATE clown68000-common) 34 | 35 | set_target_properties(clown68000-interpreter PROPERTIES 36 | C_STANDARD 90 37 | C_STANDARD_REQUIRED OFF 38 | C_EXTENSIONS OFF 39 | ) 40 | 41 | if(CC_USE_C99_INTEGERS) 42 | target_compile_definitions(clown68000-interpreter PUBLIC CC_USE_C99_INTEGERS) 43 | endif() 44 | 45 | # Microcode Generator 46 | 47 | add_executable(clown68000-microcode-generator 48 | "interpreter/microcode-generator/emit.c" 49 | "interpreter/microcode-generator/emit.h" 50 | "interpreter/microcode-generator/emit-instructions.c" 51 | "interpreter/microcode-generator/emit-instructions.h" 52 | "interpreter/microcode-generator/instruction-properties.c" 53 | "interpreter/microcode-generator/instruction-properties.h" 54 | "interpreter/microcode-generator/generator.c" 55 | ) 56 | 57 | set_target_properties(clown68000-microcode-generator PROPERTIES 58 | C_STANDARD 90 59 | C_STANDARD_REQUIRED OFF 60 | C_EXTENSIONS OFF 61 | ) 62 | 63 | if(CC_USE_C99_INTEGERS) 64 | target_compile_definitions(clown68000-microcode-generator PUBLIC CC_USE_C99_INTEGERS) 65 | endif() 66 | 67 | # Disassembler 68 | 69 | add_library(clown68000-disassembler STATIC 70 | "disassembler/disassembler.c" 71 | "disassembler/disassembler.h" 72 | "disassembler/opcode.c" 73 | "disassembler/opcode.h" 74 | ) 75 | 76 | target_link_libraries(clown68000-disassembler PRIVATE clown68000-common) 77 | 78 | set_target_properties(clown68000-disassembler PROPERTIES 79 | C_STANDARD 90 80 | C_STANDARD_REQUIRED OFF 81 | C_EXTENSIONS OFF 82 | ) 83 | 84 | if(CC_USE_C99_INTEGERS) 85 | target_compile_definitions(clown68000-disassembler PUBLIC CC_USE_C99_INTEGERS) 86 | endif() 87 | 88 | # Disassembler Tool 89 | 90 | add_executable(clown68000-disassembler-tool 91 | "disassembler/main.c" 92 | ) 93 | 94 | target_link_libraries(clown68000-disassembler-tool PRIVATE clown68000-disassembler) 95 | 96 | set_target_properties(clown68000-disassembler-tool PROPERTIES 97 | C_STANDARD 90 98 | C_STANDARD_REQUIRED OFF 99 | C_EXTENSIONS OFF 100 | ) 101 | 102 | if(CC_USE_C99_INTEGERS) 103 | target_compile_definitions(clown68000-disassembler-tool PUBLIC CC_USE_C99_INTEGERS) 104 | endif() 105 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # clown68000 2 | 3 | This is an emulator for the Motorola 68000 CPU. It is written in ANSI C and 4 | licensed under the AGPLv3. This emulator implements an interpreter and focusses 5 | on performance rather than cycle-accurate behaviour. 6 | -------------------------------------------------------------------------------- /common/instruction.h: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INCLUDE_GUARD_6B0AEAE2_3B04_4765_8C50_0B1F08F445C1 20 | #define INCLUDE_GUARD_6B0AEAE2_3B04_4765_8C50_0B1F08F445C1 21 | 22 | #include "clowncommon/clowncommon.h" 23 | 24 | typedef enum Instruction 25 | { 26 | INSTRUCTION_ABCD, 27 | INSTRUCTION_ADD, 28 | INSTRUCTION_ADDA, 29 | INSTRUCTION_ADDAQ, 30 | INSTRUCTION_ADDI, 31 | INSTRUCTION_ADDQ, 32 | INSTRUCTION_ADDX, 33 | INSTRUCTION_AND, 34 | INSTRUCTION_ANDI, 35 | INSTRUCTION_ANDI_TO_CCR, 36 | INSTRUCTION_ANDI_TO_SR, 37 | INSTRUCTION_ASD_MEMORY, 38 | INSTRUCTION_ASD_REGISTER, 39 | INSTRUCTION_BCC_SHORT, 40 | INSTRUCTION_BCC_WORD, 41 | INSTRUCTION_BCHG_DYNAMIC, 42 | INSTRUCTION_BCHG_STATIC, 43 | INSTRUCTION_BCLR_DYNAMIC, 44 | INSTRUCTION_BCLR_STATIC, 45 | INSTRUCTION_BRA_SHORT, 46 | INSTRUCTION_BRA_WORD, 47 | INSTRUCTION_BSET_DYNAMIC, 48 | INSTRUCTION_BSET_STATIC, 49 | INSTRUCTION_BSR_SHORT, 50 | INSTRUCTION_BSR_WORD, 51 | INSTRUCTION_BTST_DYNAMIC, 52 | INSTRUCTION_BTST_STATIC, 53 | INSTRUCTION_CHK, 54 | INSTRUCTION_CLR, 55 | INSTRUCTION_CMP, 56 | INSTRUCTION_CMPA, 57 | INSTRUCTION_CMPI, 58 | INSTRUCTION_CMPM, 59 | INSTRUCTION_DBCC, 60 | INSTRUCTION_DIVS, 61 | INSTRUCTION_DIVU, 62 | INSTRUCTION_EOR, 63 | INSTRUCTION_EORI, 64 | INSTRUCTION_EORI_TO_CCR, 65 | INSTRUCTION_EORI_TO_SR, 66 | INSTRUCTION_EXG, 67 | INSTRUCTION_EXT, 68 | INSTRUCTION_ILLEGAL, 69 | INSTRUCTION_JMP, 70 | INSTRUCTION_JSR, 71 | INSTRUCTION_LEA, 72 | INSTRUCTION_LINK, 73 | INSTRUCTION_LSD_MEMORY, 74 | INSTRUCTION_LSD_REGISTER, 75 | INSTRUCTION_MOVE, 76 | INSTRUCTION_MOVE_FROM_SR, 77 | INSTRUCTION_MOVE_TO_CCR, 78 | INSTRUCTION_MOVE_TO_SR, 79 | INSTRUCTION_MOVE_USP, 80 | INSTRUCTION_MOVEA, 81 | INSTRUCTION_MOVEM, 82 | INSTRUCTION_MOVEP, 83 | INSTRUCTION_MOVEQ, 84 | INSTRUCTION_MULS, 85 | INSTRUCTION_MULU, 86 | INSTRUCTION_NBCD, 87 | INSTRUCTION_NEG, 88 | INSTRUCTION_NEGX, 89 | INSTRUCTION_NOP, 90 | INSTRUCTION_NOT, 91 | INSTRUCTION_OR, 92 | INSTRUCTION_ORI, 93 | INSTRUCTION_ORI_TO_CCR, 94 | INSTRUCTION_ORI_TO_SR, 95 | INSTRUCTION_PEA, 96 | INSTRUCTION_RESET, 97 | INSTRUCTION_ROD_MEMORY, 98 | INSTRUCTION_ROD_REGISTER, 99 | INSTRUCTION_ROXD_MEMORY, 100 | INSTRUCTION_ROXD_REGISTER, 101 | INSTRUCTION_RTE, 102 | INSTRUCTION_RTR, 103 | INSTRUCTION_RTS, 104 | INSTRUCTION_SBCD, 105 | INSTRUCTION_SCC, 106 | INSTRUCTION_STOP, 107 | INSTRUCTION_SUB, 108 | INSTRUCTION_SUBA, 109 | INSTRUCTION_SUBAQ, 110 | INSTRUCTION_SUBI, 111 | INSTRUCTION_SUBQ, 112 | INSTRUCTION_SUBX, 113 | INSTRUCTION_SWAP, 114 | INSTRUCTION_TAS, 115 | INSTRUCTION_TRAP, 116 | INSTRUCTION_TRAPV, 117 | INSTRUCTION_TST, 118 | INSTRUCTION_UNLK, 119 | 120 | INSTRUCTION_UNIMPLEMENTED_1, 121 | INSTRUCTION_UNIMPLEMENTED_2 122 | } Instruction; 123 | 124 | #endif /* INCLUDE_GUARD_6B0AEAE2_3B04_4765_8C50_0B1F08F445C1 */ 125 | -------------------------------------------------------------------------------- /common/opcode.c: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "opcode.h" 20 | 21 | static Instruction GetInstruction(const SplitOpcode *opcode) 22 | { 23 | Instruction instruction; 24 | 25 | instruction = INSTRUCTION_ILLEGAL; 26 | 27 | switch ((opcode->raw >> 12) & 0xF) 28 | { 29 | case 0x0: 30 | if (opcode->bit_8) 31 | { 32 | if (opcode->primary_address_mode == ADDRESS_MODE_ADDRESS_REGISTER) 33 | { 34 | instruction = INSTRUCTION_MOVEP; 35 | } 36 | else 37 | { 38 | switch (opcode->bits_6_and_7) 39 | { 40 | case 0: 41 | instruction = INSTRUCTION_BTST_DYNAMIC; 42 | break; 43 | 44 | case 1: 45 | instruction = INSTRUCTION_BCHG_DYNAMIC; 46 | break; 47 | 48 | case 2: 49 | instruction = INSTRUCTION_BCLR_DYNAMIC; 50 | break; 51 | 52 | case 3: 53 | instruction = INSTRUCTION_BSET_DYNAMIC; 54 | break; 55 | } 56 | } 57 | } 58 | else 59 | { 60 | switch (opcode->secondary_register) 61 | { 62 | case 0: 63 | if (opcode->primary_address_mode == ADDRESS_MODE_SPECIAL && opcode->primary_register == ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE) 64 | { 65 | switch (opcode->bits_6_and_7) 66 | { 67 | case 0: 68 | instruction = INSTRUCTION_ORI_TO_CCR; 69 | break; 70 | 71 | case 1: 72 | instruction = INSTRUCTION_ORI_TO_SR; 73 | break; 74 | } 75 | } 76 | else 77 | { 78 | instruction = INSTRUCTION_ORI; 79 | } 80 | 81 | break; 82 | 83 | case 1: 84 | if (opcode->primary_address_mode == ADDRESS_MODE_SPECIAL && opcode->primary_register == ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE) 85 | { 86 | switch (opcode->bits_6_and_7) 87 | { 88 | case 0: 89 | instruction = INSTRUCTION_ANDI_TO_CCR; 90 | break; 91 | 92 | case 1: 93 | instruction = INSTRUCTION_ANDI_TO_SR; 94 | break; 95 | } 96 | } 97 | else 98 | { 99 | instruction = INSTRUCTION_ANDI; 100 | } 101 | 102 | break; 103 | 104 | case 2: 105 | instruction = INSTRUCTION_SUBI; 106 | break; 107 | 108 | case 3: 109 | instruction = INSTRUCTION_ADDI; 110 | break; 111 | 112 | case 4: 113 | switch (opcode->bits_6_and_7) 114 | { 115 | case 0: 116 | instruction = INSTRUCTION_BTST_STATIC; 117 | break; 118 | 119 | case 1: 120 | instruction = INSTRUCTION_BCHG_STATIC; 121 | break; 122 | 123 | case 2: 124 | instruction = INSTRUCTION_BCLR_STATIC; 125 | break; 126 | 127 | case 3: 128 | instruction = INSTRUCTION_BSET_STATIC; 129 | break; 130 | } 131 | 132 | break; 133 | 134 | case 5: 135 | if (opcode->primary_address_mode == ADDRESS_MODE_SPECIAL && opcode->primary_register == ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE) 136 | { 137 | switch (opcode->bits_6_and_7) 138 | { 139 | case 0: 140 | instruction = INSTRUCTION_EORI_TO_CCR; 141 | break; 142 | 143 | case 1: 144 | instruction = INSTRUCTION_EORI_TO_SR; 145 | break; 146 | } 147 | } 148 | else 149 | { 150 | instruction = INSTRUCTION_EORI; 151 | } 152 | 153 | break; 154 | 155 | case 6: 156 | instruction = INSTRUCTION_CMPI; 157 | break; 158 | } 159 | } 160 | 161 | break; 162 | 163 | case 0x1: 164 | case 0x2: 165 | case 0x3: 166 | if ((opcode->raw & 0x01C0) == 0x0040) 167 | instruction = INSTRUCTION_MOVEA; 168 | else 169 | instruction = INSTRUCTION_MOVE; 170 | 171 | break; 172 | 173 | case 0x4: 174 | if (opcode->bit_8) 175 | { 176 | switch (opcode->bits_6_and_7) 177 | { 178 | case 3: 179 | instruction = INSTRUCTION_LEA; 180 | break; 181 | 182 | case 2: 183 | instruction = INSTRUCTION_CHK; 184 | break; 185 | 186 | default: 187 | break; 188 | } 189 | } 190 | else if ((opcode->raw & 0x0800) == 0) 191 | { 192 | if (opcode->bits_6_and_7 == 3) 193 | { 194 | switch (opcode->secondary_register) 195 | { 196 | case 0: 197 | instruction = INSTRUCTION_MOVE_FROM_SR; 198 | break; 199 | 200 | case 2: 201 | instruction = INSTRUCTION_MOVE_TO_CCR; 202 | break; 203 | 204 | case 3: 205 | instruction = INSTRUCTION_MOVE_TO_SR; 206 | break; 207 | } 208 | } 209 | else 210 | { 211 | switch (opcode->secondary_register) 212 | { 213 | case 0: 214 | instruction = INSTRUCTION_NEGX; 215 | break; 216 | 217 | case 1: 218 | instruction = INSTRUCTION_CLR; 219 | break; 220 | 221 | case 2: 222 | instruction = INSTRUCTION_NEG; 223 | break; 224 | 225 | case 3: 226 | instruction = INSTRUCTION_NOT; 227 | break; 228 | } 229 | } 230 | } 231 | else if ((opcode->raw & 0x0200) == 0) 232 | { 233 | if ((opcode->raw & 0x01B8) == 0x0080) 234 | instruction = INSTRUCTION_EXT; 235 | else if ((opcode->raw & 0x01C0) == 0x0000) 236 | instruction = INSTRUCTION_NBCD; 237 | else if ((opcode->raw & 0x01F8) == 0x0040) 238 | instruction = INSTRUCTION_SWAP; 239 | else if ((opcode->raw & 0x01C0) == 0x0040) 240 | instruction = INSTRUCTION_PEA; 241 | else if ((opcode->raw & 0x0B80) == 0x0880) 242 | instruction = INSTRUCTION_MOVEM; 243 | } 244 | else if (opcode->raw == 0x4AFA || opcode->raw == 0x4AFB || opcode->raw == 0x4AFC) 245 | { 246 | instruction = INSTRUCTION_ILLEGAL; 247 | } 248 | else if ((opcode->raw & 0x0FC0) == 0x0AC0) 249 | { 250 | instruction = INSTRUCTION_TAS; 251 | } 252 | else if ((opcode->raw & 0x0F00) == 0x0A00) 253 | { 254 | instruction = INSTRUCTION_TST; 255 | } 256 | else if ((opcode->raw & 0x0FF0) == 0x0E40) 257 | { 258 | instruction = INSTRUCTION_TRAP; 259 | } 260 | else if ((opcode->raw & 0x0FF8) == 0x0E50) 261 | { 262 | instruction = INSTRUCTION_LINK; 263 | } 264 | else if ((opcode->raw & 0x0FF8) == 0x0E58) 265 | { 266 | instruction = INSTRUCTION_UNLK; 267 | } 268 | else if ((opcode->raw & 0x0FF0) == 0x0E60) 269 | { 270 | instruction = INSTRUCTION_MOVE_USP; 271 | } 272 | else if ((opcode->raw & 0x0FF8) == 0x0E70) 273 | { 274 | switch (opcode->primary_register) 275 | { 276 | case 0: 277 | instruction = INSTRUCTION_RESET; 278 | break; 279 | 280 | case 1: 281 | instruction = INSTRUCTION_NOP; 282 | break; 283 | 284 | case 2: 285 | instruction = INSTRUCTION_STOP; 286 | break; 287 | 288 | case 3: 289 | instruction = INSTRUCTION_RTE; 290 | break; 291 | 292 | case 5: 293 | instruction = INSTRUCTION_RTS; 294 | break; 295 | 296 | case 6: 297 | instruction = INSTRUCTION_TRAPV; 298 | break; 299 | 300 | case 7: 301 | instruction = INSTRUCTION_RTR; 302 | break; 303 | } 304 | } 305 | else if ((opcode->raw & 0x0FC0) == 0x0E80) 306 | { 307 | instruction = INSTRUCTION_JSR; 308 | } 309 | else if ((opcode->raw & 0x0FC0) == 0x0EC0) 310 | { 311 | instruction = INSTRUCTION_JMP; 312 | } 313 | 314 | break; 315 | 316 | case 0x5: 317 | if (opcode->bits_6_and_7 == 3) 318 | { 319 | if (opcode->primary_address_mode == ADDRESS_MODE_ADDRESS_REGISTER) 320 | instruction = INSTRUCTION_DBCC; 321 | else 322 | instruction = INSTRUCTION_SCC; 323 | } 324 | else 325 | { 326 | if (opcode->primary_address_mode == ADDRESS_MODE_ADDRESS_REGISTER) 327 | instruction = opcode->bit_8 ? INSTRUCTION_SUBAQ : INSTRUCTION_ADDAQ; 328 | else 329 | instruction = opcode->bit_8 ? INSTRUCTION_SUBQ : INSTRUCTION_ADDQ; 330 | } 331 | 332 | break; 333 | 334 | case 0x6: 335 | if (opcode->secondary_register != 0) 336 | instruction = (opcode->raw & 0x00FF) == 0 ? INSTRUCTION_BCC_WORD : INSTRUCTION_BCC_SHORT; 337 | else if (opcode->bit_8) 338 | instruction = (opcode->raw & 0x00FF) == 0 ? INSTRUCTION_BSR_WORD : INSTRUCTION_BSR_SHORT; 339 | else 340 | instruction = (opcode->raw & 0x00FF) == 0 ? INSTRUCTION_BRA_WORD : INSTRUCTION_BRA_SHORT; 341 | 342 | break; 343 | 344 | case 0x7: 345 | instruction = INSTRUCTION_MOVEQ; 346 | break; 347 | 348 | case 0x8: 349 | if (opcode->bits_6_and_7 == 3) 350 | { 351 | if (opcode->bit_8) 352 | instruction = INSTRUCTION_DIVS; 353 | else 354 | instruction = INSTRUCTION_DIVU; 355 | } 356 | else 357 | { 358 | if ((opcode->raw & 0x0170) == 0x0100) 359 | instruction = INSTRUCTION_SBCD; 360 | else 361 | instruction = INSTRUCTION_OR; 362 | } 363 | 364 | break; 365 | 366 | case 0x9: 367 | if (opcode->bits_6_and_7 == 3) 368 | instruction = INSTRUCTION_SUBA; 369 | else if ((opcode->raw & 0x0130) == 0x0100) 370 | instruction = INSTRUCTION_SUBX; 371 | else 372 | instruction = INSTRUCTION_SUB; 373 | 374 | break; 375 | 376 | case 0xA: 377 | instruction = INSTRUCTION_UNIMPLEMENTED_1; 378 | break; 379 | 380 | case 0xB: 381 | if (opcode->bits_6_and_7 == 3) 382 | instruction = INSTRUCTION_CMPA; 383 | else if (!opcode->bit_8) 384 | instruction = INSTRUCTION_CMP; 385 | else if (opcode->primary_address_mode == ADDRESS_MODE_ADDRESS_REGISTER) 386 | instruction = INSTRUCTION_CMPM; 387 | else 388 | instruction = INSTRUCTION_EOR; 389 | 390 | break; 391 | 392 | case 0xC: 393 | if (opcode->bits_6_and_7 == 3) 394 | { 395 | if (opcode->bit_8) 396 | instruction = INSTRUCTION_MULS; 397 | else 398 | instruction = INSTRUCTION_MULU; 399 | } 400 | else if ((opcode->raw & 0x0130) == 0x0100) 401 | { 402 | if (opcode->bits_6_and_7 == 0) 403 | instruction = INSTRUCTION_ABCD; 404 | else 405 | instruction = INSTRUCTION_EXG; 406 | } 407 | else 408 | { 409 | instruction = INSTRUCTION_AND; 410 | } 411 | 412 | break; 413 | 414 | case 0xD: 415 | if (opcode->bits_6_and_7 == 3) 416 | instruction = INSTRUCTION_ADDA; 417 | else if ((opcode->raw & 0x0130) == 0x0100) 418 | instruction = INSTRUCTION_ADDX; 419 | else 420 | instruction = INSTRUCTION_ADD; 421 | 422 | break; 423 | 424 | case 0xE: 425 | if (opcode->bits_6_and_7 == 3) 426 | { 427 | switch (opcode->secondary_register) 428 | { 429 | case 0: 430 | instruction = INSTRUCTION_ASD_MEMORY; 431 | break; 432 | 433 | case 1: 434 | instruction = INSTRUCTION_LSD_MEMORY; 435 | break; 436 | 437 | case 2: 438 | instruction = INSTRUCTION_ROXD_MEMORY; 439 | break; 440 | 441 | case 3: 442 | instruction = INSTRUCTION_ROD_MEMORY; 443 | break; 444 | } 445 | } 446 | else 447 | { 448 | switch (opcode->raw & 0x0018) 449 | { 450 | case 0x0000: 451 | instruction = INSTRUCTION_ASD_REGISTER; 452 | break; 453 | 454 | case 0x0008: 455 | instruction = INSTRUCTION_LSD_REGISTER; 456 | break; 457 | 458 | case 0x0010: 459 | instruction = INSTRUCTION_ROXD_REGISTER; 460 | break; 461 | 462 | case 0x0018: 463 | instruction = INSTRUCTION_ROD_REGISTER; 464 | break; 465 | } 466 | } 467 | 468 | break; 469 | 470 | case 0xF: 471 | instruction = INSTRUCTION_UNIMPLEMENTED_2; 472 | break; 473 | } 474 | 475 | return instruction; 476 | } 477 | 478 | Instruction DecodeOpcode(SplitOpcode* const split_opcode, const unsigned int opcode) 479 | { 480 | split_opcode->raw = opcode; 481 | 482 | split_opcode->bits_6_and_7 = (split_opcode->raw >> 6) & 3; 483 | split_opcode->bit_8 = (split_opcode->raw & 0x100) != 0; 484 | 485 | split_opcode->primary_register = (split_opcode->raw >> 0) & 7; 486 | split_opcode->primary_address_mode = (AddressMode)((split_opcode->raw >> 3) & 7); 487 | split_opcode->secondary_address_mode = (AddressMode)((split_opcode->raw >> 6) & 7); 488 | split_opcode->secondary_register = (split_opcode->raw >> 9) & 7; 489 | 490 | return GetInstruction(split_opcode); 491 | } 492 | -------------------------------------------------------------------------------- /common/opcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INCLUDE_GUARD_11BFE06C_ADE3_4F4B_AFB3_5854B5D48789 20 | #define INCLUDE_GUARD_11BFE06C_ADE3_4F4B_AFB3_5854B5D48789 21 | 22 | #include "clowncommon/clowncommon.h" 23 | 24 | #include "instruction.h" 25 | 26 | typedef enum AddressMode 27 | { 28 | ADDRESS_MODE_DATA_REGISTER = 0, 29 | ADDRESS_MODE_ADDRESS_REGISTER = 1, 30 | ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT = 2, 31 | ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT = 3, 32 | ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT = 4, 33 | ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT = 5, 34 | ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_INDEX = 6, 35 | ADDRESS_MODE_SPECIAL = 7 36 | } AddressMode; 37 | 38 | typedef enum AddressModeSpecial 39 | { 40 | ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_SHORT = 0, 41 | ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_LONG = 1, 42 | ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_DISPLACEMENT = 2, 43 | ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_INDEX = 3, 44 | ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE = 4 45 | } AddressModeSpecial; 46 | 47 | typedef struct SplitOpcode 48 | { 49 | unsigned int raw; 50 | 51 | unsigned int primary_register; 52 | unsigned int secondary_register; 53 | unsigned int bits_6_and_7; 54 | 55 | AddressMode primary_address_mode; 56 | AddressMode secondary_address_mode; 57 | 58 | cc_bool bit_8; 59 | } SplitOpcode; 60 | 61 | Instruction DecodeOpcode(SplitOpcode *split_opcode, unsigned int opcode); 62 | 63 | #endif /* INCLUDE_GUARD_11BFE06C_ADE3_4F4B_AFB3_5854B5D48789 */ 64 | -------------------------------------------------------------------------------- /disassembler/disassembler.c: -------------------------------------------------------------------------------- 1 | #include "disassembler.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "opcode.h" 8 | 9 | typedef struct Stuff 10 | { 11 | unsigned long address; 12 | Clown68000_Disassemble_ReadCallback read_callback; 13 | void *user_data; 14 | } Stuff; 15 | 16 | static long ReadWord(Stuff* const stuff) 17 | { 18 | stuff->address += 2; 19 | return stuff->read_callback(stuff->user_data); 20 | } 21 | 22 | static size_t UnsignedHexToString(char* const buffer, const unsigned long hex) 23 | { 24 | static const char lut[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 25 | 26 | size_t index, subindex; 27 | unsigned int i; 28 | 29 | index = 0; 30 | 31 | if (hex >= 0xA) 32 | buffer[index++] = '$'; 33 | 34 | subindex = 0; 35 | 36 | for (i = 0; i < 8; ++i) 37 | { 38 | const char character = lut[(hex >> (4 * (8 - 1 - i))) & 0xF]; 39 | 40 | if (character != '0' || subindex != 0 || i == 7) 41 | buffer[index + subindex++] = character; 42 | } 43 | 44 | index += subindex; 45 | 46 | return index; 47 | } 48 | 49 | static size_t SignedHexToString(char* const buffer, const unsigned long hex) 50 | { 51 | if ((hex & 0x80000000) != 0) 52 | { 53 | buffer[0] = '-'; 54 | return 1 + UnsignedHexToString(&buffer[1], 0 - hex); 55 | } 56 | else 57 | { 58 | return UnsignedHexToString(buffer, hex); 59 | } 60 | } 61 | 62 | #define GET_STRING_DATA(NAME) \ 63 | size = sizeof(NAME) - 1; \ 64 | string = NAME; \ 65 | break 66 | 67 | static size_t GetInstructionName(char* const buffer, const Instruction instruction) 68 | { 69 | size_t size; 70 | const char *string; 71 | 72 | switch (instruction) 73 | { 74 | default: 75 | 76 | case INSTRUCTION_ABCD: 77 | GET_STRING_DATA("abcd"); 78 | 79 | case INSTRUCTION_ADD: 80 | GET_STRING_DATA("add"); 81 | 82 | case INSTRUCTION_ADDA: 83 | GET_STRING_DATA("adda"); 84 | 85 | case INSTRUCTION_ADDAQ: 86 | case INSTRUCTION_ADDQ: 87 | GET_STRING_DATA("addq"); 88 | 89 | case INSTRUCTION_ADDI: 90 | GET_STRING_DATA("addi"); 91 | 92 | case INSTRUCTION_ADDX: 93 | GET_STRING_DATA("addx"); 94 | 95 | case INSTRUCTION_AND: 96 | GET_STRING_DATA("and"); 97 | 98 | case INSTRUCTION_ANDI: 99 | case INSTRUCTION_ANDI_TO_CCR: 100 | case INSTRUCTION_ANDI_TO_SR: 101 | GET_STRING_DATA("andi"); 102 | 103 | case INSTRUCTION_ASD_MEMORY: 104 | case INSTRUCTION_ASD_REGISTER: 105 | GET_STRING_DATA("as"); 106 | 107 | case INSTRUCTION_BCC_SHORT: 108 | case INSTRUCTION_BCC_WORD: 109 | GET_STRING_DATA("b"); 110 | 111 | case INSTRUCTION_BCHG_DYNAMIC: 112 | case INSTRUCTION_BCHG_STATIC: 113 | GET_STRING_DATA("bchg"); 114 | 115 | case INSTRUCTION_BCLR_DYNAMIC: 116 | case INSTRUCTION_BCLR_STATIC: 117 | GET_STRING_DATA("bclr"); 118 | 119 | case INSTRUCTION_BRA_SHORT: 120 | case INSTRUCTION_BRA_WORD: 121 | GET_STRING_DATA("bra"); 122 | 123 | case INSTRUCTION_BSET_DYNAMIC: 124 | case INSTRUCTION_BSET_STATIC: 125 | GET_STRING_DATA("bset"); 126 | 127 | case INSTRUCTION_BSR_SHORT: 128 | case INSTRUCTION_BSR_WORD: 129 | GET_STRING_DATA("bsr"); 130 | 131 | case INSTRUCTION_BTST_DYNAMIC: 132 | case INSTRUCTION_BTST_STATIC: 133 | GET_STRING_DATA("btst"); 134 | 135 | case INSTRUCTION_CHK: 136 | GET_STRING_DATA("chk"); 137 | 138 | case INSTRUCTION_CLR: 139 | GET_STRING_DATA("clr"); 140 | 141 | case INSTRUCTION_CMP: 142 | GET_STRING_DATA("cmp"); 143 | 144 | case INSTRUCTION_CMPA: 145 | GET_STRING_DATA("cmpa"); 146 | 147 | case INSTRUCTION_CMPI: 148 | GET_STRING_DATA("cmpi"); 149 | 150 | case INSTRUCTION_CMPM: 151 | GET_STRING_DATA("cmpm"); 152 | 153 | case INSTRUCTION_DBCC: 154 | GET_STRING_DATA("db"); 155 | 156 | case INSTRUCTION_DIVS: 157 | GET_STRING_DATA("divs"); 158 | 159 | case INSTRUCTION_DIVU: 160 | GET_STRING_DATA("divu"); 161 | 162 | case INSTRUCTION_EOR: 163 | GET_STRING_DATA("eor"); 164 | 165 | case INSTRUCTION_EORI: 166 | case INSTRUCTION_EORI_TO_CCR: 167 | case INSTRUCTION_EORI_TO_SR: 168 | GET_STRING_DATA("eori"); 169 | 170 | case INSTRUCTION_EXG: 171 | GET_STRING_DATA("exg"); 172 | 173 | case INSTRUCTION_EXT: 174 | GET_STRING_DATA("ext"); 175 | 176 | case INSTRUCTION_ILLEGAL: 177 | GET_STRING_DATA("illegal"); 178 | 179 | case INSTRUCTION_JMP: 180 | GET_STRING_DATA("jmp"); 181 | 182 | case INSTRUCTION_JSR: 183 | GET_STRING_DATA("jsr"); 184 | 185 | case INSTRUCTION_LEA: 186 | GET_STRING_DATA("lea"); 187 | 188 | case INSTRUCTION_LINK: 189 | GET_STRING_DATA("link"); 190 | 191 | case INSTRUCTION_LSD_MEMORY: 192 | case INSTRUCTION_LSD_REGISTER: 193 | GET_STRING_DATA("ls"); 194 | 195 | case INSTRUCTION_MOVE: 196 | case INSTRUCTION_MOVE_FROM_SR: 197 | case INSTRUCTION_MOVE_TO_CCR: 198 | case INSTRUCTION_MOVE_TO_SR: 199 | case INSTRUCTION_MOVE_USP: 200 | GET_STRING_DATA("move"); 201 | 202 | case INSTRUCTION_MOVEA: 203 | GET_STRING_DATA("movea"); 204 | 205 | case INSTRUCTION_MOVEM: 206 | GET_STRING_DATA("movem"); 207 | 208 | case INSTRUCTION_MOVEP: 209 | GET_STRING_DATA("movep"); 210 | 211 | case INSTRUCTION_MOVEQ: 212 | GET_STRING_DATA("moveq"); 213 | 214 | case INSTRUCTION_MULS: 215 | GET_STRING_DATA("muls"); 216 | 217 | case INSTRUCTION_MULU: 218 | GET_STRING_DATA("mulu"); 219 | 220 | case INSTRUCTION_NBCD: 221 | GET_STRING_DATA("nbcd"); 222 | 223 | case INSTRUCTION_NEG: 224 | GET_STRING_DATA("neg"); 225 | 226 | case INSTRUCTION_NEGX: 227 | GET_STRING_DATA("negx"); 228 | 229 | case INSTRUCTION_NOP: 230 | GET_STRING_DATA("nop"); 231 | 232 | case INSTRUCTION_NOT: 233 | GET_STRING_DATA("not"); 234 | 235 | case INSTRUCTION_OR: 236 | GET_STRING_DATA("or"); 237 | 238 | case INSTRUCTION_ORI: 239 | case INSTRUCTION_ORI_TO_CCR: 240 | case INSTRUCTION_ORI_TO_SR: 241 | GET_STRING_DATA("ori"); 242 | 243 | case INSTRUCTION_PEA: 244 | GET_STRING_DATA("pea"); 245 | 246 | case INSTRUCTION_RESET: 247 | GET_STRING_DATA("reset"); 248 | 249 | case INSTRUCTION_ROD_MEMORY: 250 | case INSTRUCTION_ROD_REGISTER: 251 | GET_STRING_DATA("ro"); 252 | 253 | case INSTRUCTION_ROXD_MEMORY: 254 | case INSTRUCTION_ROXD_REGISTER: 255 | GET_STRING_DATA("rox"); 256 | 257 | case INSTRUCTION_RTE: 258 | GET_STRING_DATA("rte"); 259 | 260 | case INSTRUCTION_RTR: 261 | GET_STRING_DATA("rtr"); 262 | 263 | case INSTRUCTION_RTS: 264 | GET_STRING_DATA("rts"); 265 | 266 | case INSTRUCTION_SBCD: 267 | GET_STRING_DATA("sbcd"); 268 | 269 | case INSTRUCTION_SCC: 270 | GET_STRING_DATA("s"); 271 | 272 | case INSTRUCTION_STOP: 273 | GET_STRING_DATA("stop"); 274 | 275 | case INSTRUCTION_SUB: 276 | GET_STRING_DATA("sub"); 277 | 278 | case INSTRUCTION_SUBA: 279 | GET_STRING_DATA("suba"); 280 | 281 | case INSTRUCTION_SUBAQ: 282 | case INSTRUCTION_SUBQ: 283 | GET_STRING_DATA("subq"); 284 | 285 | case INSTRUCTION_SUBI: 286 | GET_STRING_DATA("subi"); 287 | 288 | case INSTRUCTION_SUBX: 289 | GET_STRING_DATA("subx"); 290 | 291 | case INSTRUCTION_SWAP: 292 | GET_STRING_DATA("swap"); 293 | 294 | case INSTRUCTION_TAS: 295 | GET_STRING_DATA("tas"); 296 | 297 | case INSTRUCTION_TRAP: 298 | GET_STRING_DATA("trap"); 299 | 300 | case INSTRUCTION_TRAPV: 301 | GET_STRING_DATA("trapv"); 302 | 303 | case INSTRUCTION_TST: 304 | GET_STRING_DATA("tst"); 305 | 306 | case INSTRUCTION_UNLK: 307 | GET_STRING_DATA("unlk"); 308 | 309 | case INSTRUCTION_UNIMPLEMENTED_1: 310 | GET_STRING_DATA("[invalid instruction (1)]"); 311 | 312 | case INSTRUCTION_UNIMPLEMENTED_2: 313 | GET_STRING_DATA("[invalid instruction (2)]"); 314 | } 315 | 316 | memcpy(buffer, string, size); 317 | return size; 318 | } 319 | 320 | static size_t GetOpcodeConditionName(char* const buffer, const unsigned int opcode) 321 | { 322 | size_t size; 323 | const char *string; 324 | 325 | switch ((opcode >> 8) & 0xF) 326 | { 327 | case 0x0: 328 | /* True */ 329 | GET_STRING_DATA("t"); 330 | 331 | case 0x1: 332 | /* False */ 333 | GET_STRING_DATA("f"); 334 | 335 | case 0x2: 336 | /* Higher */ 337 | GET_STRING_DATA("hi"); 338 | 339 | case 0x3: 340 | /* Lower or same */ 341 | GET_STRING_DATA("ls"); 342 | 343 | case 0x4: 344 | /* Carry clear */ 345 | GET_STRING_DATA("cc"); 346 | 347 | case 0x5: 348 | /* Carry set */ 349 | GET_STRING_DATA("cs"); 350 | 351 | case 0x6: 352 | /* Not equal */ 353 | GET_STRING_DATA("ne"); 354 | 355 | case 0x7: 356 | /* Equal */ 357 | GET_STRING_DATA("eq"); 358 | 359 | case 0x8: 360 | /* Overflow clear */ 361 | GET_STRING_DATA("vc"); 362 | 363 | case 0x9: 364 | /* Overflow set */ 365 | GET_STRING_DATA("vs"); 366 | 367 | case 0xA: 368 | /* Plus */ 369 | GET_STRING_DATA("pl"); 370 | 371 | case 0xB: 372 | /* Minus */ 373 | GET_STRING_DATA("mi"); 374 | 375 | case 0xC: 376 | /* Greater or equal */ 377 | GET_STRING_DATA("ge"); 378 | 379 | case 0xD: 380 | /* Less than */ 381 | GET_STRING_DATA("lt"); 382 | 383 | case 0xE: 384 | /* Greater than */ 385 | GET_STRING_DATA("gt"); 386 | 387 | case 0xF: 388 | /* Less or equal */ 389 | GET_STRING_DATA("le"); 390 | } 391 | 392 | memcpy(buffer, string, size); 393 | return size; 394 | } 395 | 396 | #undef GET_STRING_DATA 397 | 398 | static size_t GetAddressRegister(char* const buffer, unsigned int address_register) 399 | { 400 | if (address_register == 7) 401 | { 402 | buffer[0] = 's'; 403 | buffer[1] = 'p'; 404 | } 405 | else 406 | { 407 | buffer[0] = 'a'; 408 | buffer[1] = '0' + address_register; 409 | } 410 | 411 | return 2; 412 | } 413 | 414 | static size_t GetOperandName(Stuff* const stuff, char* const buffer, const DecodedOpcode* const decoded_opcode, const cc_bool operand_is_destination) 415 | { 416 | size_t index = 0; 417 | const Operand* const operand = &decoded_opcode->operands[operand_is_destination ? 1 : 0]; 418 | 419 | switch (operand->address_mode) 420 | { 421 | case OPERAND_ADDRESS_MODE_DATA_REGISTER: 422 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER: 423 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT: 424 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT: 425 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT: 426 | if (operand->address_mode == OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT) 427 | buffer[index++] = '-'; 428 | 429 | switch (operand->address_mode) 430 | { 431 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT: 432 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT: 433 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT: 434 | buffer[index++] = '('; 435 | break; 436 | 437 | default: 438 | break; 439 | } 440 | 441 | switch (operand->address_mode) 442 | { 443 | case OPERAND_ADDRESS_MODE_DATA_REGISTER: 444 | buffer[index++] = 'd'; 445 | buffer[index++] = '0' + operand->address_mode_register; 446 | break; 447 | 448 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER: 449 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT: 450 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT: 451 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT: 452 | index += GetAddressRegister(&buffer[index], operand->address_mode_register); 453 | break; 454 | 455 | default: 456 | break; 457 | } 458 | 459 | switch (operand->address_mode) 460 | { 461 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT: 462 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT: 463 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT: 464 | buffer[index++] = ')'; 465 | break; 466 | 467 | default: 468 | break; 469 | } 470 | 471 | if (operand->address_mode == OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT) 472 | buffer[index++] = '+'; 473 | 474 | break; 475 | 476 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT: 477 | { 478 | const unsigned long data = ReadWord(stuff); 479 | index += SignedHexToString(&buffer[index], CC_SIGN_EXTEND_ULONG(15, data)); 480 | buffer[index++] = '('; 481 | index += GetAddressRegister(&buffer[index], operand->address_mode_register); 482 | buffer[index++] = ')'; 483 | break; 484 | } 485 | 486 | case OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_INDEX: 487 | { 488 | const unsigned long data = ReadWord(stuff); 489 | const unsigned long literal = CC_SIGN_EXTEND_ULONG(7, data); 490 | 491 | if (literal != 0) 492 | index += SignedHexToString(&buffer[index], literal); 493 | 494 | buffer[index++] = '('; 495 | index += GetAddressRegister(&buffer[index], operand->address_mode_register); 496 | buffer[index++] = ','; 497 | if ((data & 0x8000) != 0) 498 | { 499 | index += GetAddressRegister(&buffer[index], ((data >> 12) & 7)); 500 | } 501 | else 502 | { 503 | buffer[index++] = 'd'; 504 | buffer[index++] = '0' + ((data >> 12) & 7); 505 | } 506 | buffer[index++] = '.'; 507 | buffer[index++] = (data & 0x800) != 0 ? 'l' : 'w'; 508 | buffer[index++] = ')'; 509 | 510 | break; 511 | } 512 | 513 | case OPERAND_ADDRESS_MODE_SPECIAL: 514 | { 515 | const unsigned long address = stuff->address; 516 | const unsigned long data = ReadWord(stuff); 517 | 518 | switch (operand->address_mode_register) 519 | { 520 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_SHORT: 521 | buffer[index++] = '('; 522 | index += UnsignedHexToString(&buffer[index], CC_SIGN_EXTEND_ULONG(15, data)); 523 | buffer[index++] = ')'; 524 | buffer[index++] = '.'; 525 | buffer[index++] = 'w'; 526 | break; 527 | 528 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_LONG: 529 | buffer[index++] = '('; 530 | index += UnsignedHexToString(&buffer[index], (data << 16) | ReadWord(stuff)); 531 | buffer[index++] = ')'; 532 | buffer[index++] = '.'; 533 | buffer[index++] = 'l'; 534 | break; 535 | 536 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_DISPLACEMENT: 537 | index += UnsignedHexToString(&buffer[index], address + CC_SIGN_EXTEND_ULONG(15, data)); 538 | buffer[index++] = '('; 539 | buffer[index++] = 'p'; 540 | buffer[index++] = 'c'; 541 | buffer[index++] = ')'; 542 | break; 543 | 544 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_INDEX: 545 | index += UnsignedHexToString(&buffer[index], address + CC_SIGN_EXTEND_ULONG(7, data)); 546 | buffer[index++] = '('; 547 | buffer[index++] = 'p'; 548 | buffer[index++] = 'c'; 549 | buffer[index++] = ','; 550 | 551 | if ((data & 0x8000) != 0) 552 | { 553 | index += GetAddressRegister(&buffer[index], ((data >> 12) & 7)); 554 | } 555 | else 556 | { 557 | buffer[index++] = 'd'; 558 | buffer[index++] = '0' + ((data >> 12) & 7); 559 | } 560 | 561 | buffer[index++] = '.'; 562 | buffer[index++] = (data & 0x800) != 0 ? 'l' : 'w'; 563 | buffer[index++] = ')'; 564 | break; 565 | 566 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE: 567 | { 568 | unsigned long full_data, sign_extended_full_data; 569 | 570 | buffer[index++] = '#'; 571 | 572 | switch (operand->operation_size) 573 | { 574 | case OPERATION_SIZE_LONGWORD: 575 | full_data = (data << 16) | ReadWord(stuff); 576 | sign_extended_full_data = full_data; 577 | break; 578 | 579 | case OPERATION_SIZE_WORD: 580 | full_data = data; 581 | sign_extended_full_data = CC_SIGN_EXTEND_ULONG(15, data); 582 | break; 583 | 584 | case OPERATION_SIZE_BYTE: 585 | default: 586 | full_data = data & 0xFF; 587 | sign_extended_full_data = CC_SIGN_EXTEND_ULONG(7, data); 588 | break; 589 | } 590 | 591 | if (sign_extended_full_data >= (unsigned long)-0x10) 592 | index += SignedHexToString(&buffer[index], sign_extended_full_data); 593 | else 594 | index += UnsignedHexToString(&buffer[index], full_data); 595 | 596 | break; 597 | } 598 | 599 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE_ADDRESS: 600 | if (operand->operation_size == OPERATION_SIZE_LONGWORD) 601 | index += UnsignedHexToString(&buffer[index], address + ((data << 16) | ReadWord(stuff))); 602 | else 603 | index += UnsignedHexToString(&buffer[index], address + CC_SIGN_EXTEND_ULONG(15, data)); 604 | 605 | break; 606 | 607 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST: 608 | case OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST_REVERSED: 609 | { 610 | const unsigned int xor_mask = operand->address_mode_register == OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST_REVERSED ? 0xF : 0; 611 | 612 | unsigned int i; 613 | cc_bool first; 614 | 615 | first = cc_true; 616 | 617 | for (i = 0; i < 16; ++i) 618 | { 619 | if ((data & (1 << (i ^ xor_mask))) != 0) 620 | { 621 | static const char registers[][3] = { 622 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 623 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 624 | }; 625 | 626 | if (first) 627 | first = cc_false; 628 | else 629 | buffer[index++] = '/'; 630 | 631 | buffer[index++] = registers[i][0]; 632 | buffer[index++] = registers[i][1]; 633 | 634 | ++i; 635 | 636 | if (i < 16 && (data & (1 << (i ^ xor_mask))) != 0) 637 | { 638 | for (i = i + 1; i < 16; ++i) 639 | if ((data & (1 << (i ^ xor_mask))) == 0) 640 | break; 641 | 642 | --i; 643 | 644 | buffer[index++] = '-'; 645 | buffer[index++] = registers[i][0]; 646 | buffer[index++] = registers[i][1]; 647 | } 648 | } 649 | } 650 | 651 | break; 652 | } 653 | } 654 | 655 | break; 656 | } 657 | 658 | case OPERAND_ADDRESS_MODE_STATUS_REGISTER: 659 | buffer[index++] = 's'; 660 | buffer[index++] = 'r'; 661 | break; 662 | 663 | case OPERAND_ADDRESS_MODE_CONDITION_CODE_REGISTER: 664 | buffer[index++] = 'c'; 665 | buffer[index++] = 'c'; 666 | buffer[index++] = 'r'; 667 | break; 668 | 669 | case OPERAND_ADDRESS_MODE_NONE: 670 | assert(0); 671 | break; 672 | 673 | case OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE: 674 | buffer[index++] = '#'; 675 | index += SignedHexToString(&buffer[index], CC_SIGN_EXTEND_ULONG(operand->operation_size == OPERATION_SIZE_BYTE ? 7 : operand->operation_size == OPERATION_SIZE_WORD ? 15 : 31, operand->address_mode_register)); 676 | break; 677 | 678 | case OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE_ADDRESS: 679 | index += UnsignedHexToString(&buffer[index], stuff->address + CC_SIGN_EXTEND_ULONG(operand->operation_size == OPERATION_SIZE_BYTE ? 7 : operand->operation_size == OPERATION_SIZE_WORD ? 15 : 31, operand->address_mode_register)); 680 | break; 681 | 682 | case OPERAND_ADDRESS_MODE_USER_STACK_POINTER: 683 | buffer[index++] = 'u'; 684 | buffer[index++] = 's'; 685 | buffer[index++] = 'p'; 686 | break; 687 | } 688 | 689 | return index; 690 | } 691 | 692 | void Clown68000_Disassemble(const unsigned long address, const unsigned int max_instructions, const Clown68000_Disassemble_ReadCallback read_callback, const Clown68000_Disassemble_PrintCallback print_callback, const void* const user_data) 693 | { 694 | unsigned int i; 695 | Stuff stuff; 696 | 697 | stuff.address = address; 698 | stuff.read_callback = read_callback; 699 | stuff.user_data = (void*)user_data; 700 | 701 | for (i = 0; i < max_instructions; ++i) 702 | { 703 | char string_buffer[0x80]; 704 | size_t index; 705 | DecodedOpcode decoded_opcode; 706 | SplitOpcode split_opcode; 707 | long opcode; 708 | 709 | sprintf(string_buffer, "%08lX: ", stuff.address); 710 | index = 8 + 2; 711 | 712 | opcode = ReadWord(&stuff); 713 | 714 | if (opcode == -1) 715 | return; 716 | 717 | DecodeOpcodeAndOperands(&decoded_opcode, &split_opcode, opcode); 718 | 719 | index += GetInstructionName(&string_buffer[index], decoded_opcode.instruction); 720 | 721 | /* Instruction name suffix and special operands. */ 722 | switch (decoded_opcode.instruction) 723 | { 724 | case INSTRUCTION_BCC_SHORT: 725 | case INSTRUCTION_BCC_WORD: 726 | case INSTRUCTION_DBCC: 727 | case INSTRUCTION_SCC: 728 | index += GetOpcodeConditionName(&string_buffer[index], opcode); 729 | break; 730 | 731 | case INSTRUCTION_ASD_MEMORY: 732 | case INSTRUCTION_ASD_REGISTER: 733 | case INSTRUCTION_LSD_MEMORY: 734 | case INSTRUCTION_LSD_REGISTER: 735 | case INSTRUCTION_ROD_MEMORY: 736 | case INSTRUCTION_ROD_REGISTER: 737 | case INSTRUCTION_ROXD_MEMORY: 738 | case INSTRUCTION_ROXD_REGISTER: 739 | string_buffer[index++] = split_opcode.bit_8 ? 'l' : 'r'; 740 | break; 741 | 742 | default: 743 | break; 744 | } 745 | 746 | switch (decoded_opcode.instruction) 747 | { 748 | case INSTRUCTION_DBCC: 749 | case INSTRUCTION_LEA: 750 | case INSTRUCTION_MOVEQ: 751 | case INSTRUCTION_PEA: 752 | case INSTRUCTION_EXG: 753 | case INSTRUCTION_SWAP: 754 | case INSTRUCTION_LINK: 755 | case INSTRUCTION_STOP: 756 | break; 757 | 758 | default: 759 | if (decoded_opcode.size != OPERATION_SIZE_NONE) 760 | { 761 | string_buffer[index++] = '.'; 762 | string_buffer[index++] = decoded_opcode.size == OPERATION_SIZE_SHORT ? 's' : decoded_opcode.size == OPERATION_SIZE_BYTE ? 'b' : decoded_opcode.size == OPERATION_SIZE_WORD ? 'w' : 'l'; 763 | } 764 | 765 | break; 766 | } 767 | 768 | while (index < 18) 769 | string_buffer[index++] = ' '; 770 | 771 | if (decoded_opcode.operands[0].address_mode != OPERAND_ADDRESS_MODE_NONE) 772 | index += GetOperandName(&stuff, &string_buffer[index], &decoded_opcode, cc_false); 773 | 774 | if (decoded_opcode.operands[0].address_mode != OPERAND_ADDRESS_MODE_NONE && decoded_opcode.operands[1].address_mode != OPERAND_ADDRESS_MODE_NONE) 775 | string_buffer[index++] = ','; 776 | 777 | if (decoded_opcode.operands[1].address_mode != OPERAND_ADDRESS_MODE_NONE) 778 | index += GetOperandName(&stuff, &string_buffer[index], &decoded_opcode, cc_true); 779 | 780 | string_buffer[index++] = '\0'; 781 | 782 | print_callback((void*)user_data, string_buffer); 783 | 784 | /* Halt when encountering a terminating instruction. */ 785 | switch (decoded_opcode.instruction) 786 | { 787 | case INSTRUCTION_BRA_SHORT: 788 | case INSTRUCTION_BRA_WORD: 789 | case INSTRUCTION_JMP: 790 | case INSTRUCTION_RESET: 791 | case INSTRUCTION_RTE: 792 | case INSTRUCTION_RTR: 793 | case INSTRUCTION_RTS: 794 | case INSTRUCTION_TRAP: 795 | case INSTRUCTION_TRAPV: 796 | return; 797 | 798 | default: 799 | break; 800 | } 801 | } 802 | } 803 | -------------------------------------------------------------------------------- /disassembler/disassembler.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_GUARD_B0B82496_E262_49CB_927E_C4CA05531920 2 | #define INCLUDE_GUARD_B0B82496_E262_49CB_927E_C4CA05531920 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef long (*Clown68000_Disassemble_ReadCallback)(void *user_data); 9 | typedef void (*Clown68000_Disassemble_PrintCallback)(void *user_data, const char *string); 10 | 11 | void Clown68000_Disassemble(unsigned long address, unsigned int max_instructions, Clown68000_Disassemble_ReadCallback read_callback, Clown68000_Disassemble_PrintCallback print_callback, const void *user_data); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* INCLUDE_GUARD_B0B82496_E262_49CB_927E_C4CA05531920 */ 18 | -------------------------------------------------------------------------------- /disassembler/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "disassembler.h" 6 | 7 | static long ReadCallback(void *user_data) 8 | { 9 | unsigned char bytes[2]; 10 | 11 | (void)user_data; 12 | 13 | if (fread(bytes, 2, 1, (FILE*)user_data) != 1) 14 | return -1; 15 | 16 | return ((long)bytes[0] << 8) | bytes[1]; 17 | } 18 | 19 | static void PrintCallback(void *user_data, const char *string) 20 | { 21 | (void)user_data; 22 | 23 | fprintf(stdout, "%s\n", string); 24 | } 25 | 26 | int main(const int argc, char** const argv) 27 | { 28 | int exit_code = EXIT_FAILURE; 29 | 30 | if (argc < 3) 31 | { 32 | fprintf(stderr, "Usage: %s [path to file] [address]\n", argv[0]); 33 | } 34 | else 35 | { 36 | FILE* const file = fopen(argv[1], "rb"); 37 | 38 | if (file == NULL) 39 | { 40 | fputs("Error: Could not open file for reading!\n", stderr); 41 | } 42 | else 43 | { 44 | const unsigned long address = strtoul(argv[2], NULL, 0); 45 | 46 | fseek(file, address, SEEK_SET); 47 | Clown68000_Disassemble(address, 1000, ReadCallback, PrintCallback, file); 48 | fclose(file); 49 | 50 | exit_code = EXIT_SUCCESS; 51 | } 52 | } 53 | 54 | return exit_code; 55 | } 56 | -------------------------------------------------------------------------------- /disassembler/opcode.c: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "opcode.h" 20 | 21 | static OperationSize GetSize(const Instruction instruction, const SplitOpcode* const opcode) 22 | { 23 | OperationSize operation_size; 24 | 25 | operation_size = OPERATION_SIZE_NONE; 26 | 27 | switch (instruction) 28 | { 29 | case INSTRUCTION_ORI_TO_CCR: 30 | case INSTRUCTION_ANDI_TO_CCR: 31 | case INSTRUCTION_EORI_TO_CCR: 32 | case INSTRUCTION_NBCD: 33 | case INSTRUCTION_TAS: 34 | case INSTRUCTION_SCC: 35 | case INSTRUCTION_SBCD: 36 | case INSTRUCTION_ABCD: 37 | /* Hardcoded to a byte. */ 38 | operation_size = OPERATION_SIZE_BYTE; 39 | break; 40 | 41 | case INSTRUCTION_ORI_TO_SR: 42 | case INSTRUCTION_ANDI_TO_SR: 43 | case INSTRUCTION_EORI_TO_SR: 44 | case INSTRUCTION_MOVE_FROM_SR: 45 | case INSTRUCTION_MOVE_TO_SR: 46 | case INSTRUCTION_MOVE_TO_CCR: 47 | case INSTRUCTION_LINK: 48 | case INSTRUCTION_CHK: 49 | case INSTRUCTION_DBCC: 50 | case INSTRUCTION_ASD_MEMORY: 51 | case INSTRUCTION_LSD_MEMORY: 52 | case INSTRUCTION_ROXD_MEMORY: 53 | case INSTRUCTION_ROD_MEMORY: 54 | case INSTRUCTION_STOP: 55 | case INSTRUCTION_BRA_WORD: 56 | case INSTRUCTION_BSR_WORD: 57 | case INSTRUCTION_BCC_WORD: 58 | case INSTRUCTION_DIVU: 59 | case INSTRUCTION_DIVS: 60 | case INSTRUCTION_MULU: 61 | case INSTRUCTION_MULS: 62 | /* Hardcoded to a word. */ 63 | operation_size = OPERATION_SIZE_WORD; 64 | break; 65 | 66 | case INSTRUCTION_ADDAQ: 67 | case INSTRUCTION_SUBAQ: 68 | case INSTRUCTION_SWAP: 69 | case INSTRUCTION_LEA: 70 | case INSTRUCTION_MOVEQ: 71 | case INSTRUCTION_MOVE_USP: 72 | /* Hardcoded to a longword. */ 73 | operation_size = OPERATION_SIZE_LONGWORD; 74 | break; 75 | 76 | case INSTRUCTION_SUBA: 77 | case INSTRUCTION_CMPA: 78 | case INSTRUCTION_ADDA: 79 | /* Word or longword based on bit 8. */ 80 | operation_size = opcode->bit_8 ? OPERATION_SIZE_LONGWORD : OPERATION_SIZE_WORD; 81 | break; 82 | 83 | case INSTRUCTION_BTST_STATIC: 84 | case INSTRUCTION_BCHG_STATIC: 85 | case INSTRUCTION_BCLR_STATIC: 86 | case INSTRUCTION_BSET_STATIC: 87 | case INSTRUCTION_BTST_DYNAMIC: 88 | case INSTRUCTION_BCHG_DYNAMIC: 89 | case INSTRUCTION_BCLR_DYNAMIC: 90 | case INSTRUCTION_BSET_DYNAMIC: 91 | /* 4 if register - 1 if memory. */ 92 | operation_size = opcode->primary_address_mode == ADDRESS_MODE_DATA_REGISTER ? OPERATION_SIZE_LONGWORD : OPERATION_SIZE_BYTE; 93 | break; 94 | 95 | case INSTRUCTION_MOVEA: 96 | case INSTRUCTION_MOVE: 97 | /* Derived from an odd bitfield. */ 98 | switch (opcode->raw & 0x3000) 99 | { 100 | case 0x1000: 101 | operation_size = OPERATION_SIZE_BYTE; 102 | break; 103 | 104 | case 0x2000: 105 | operation_size = OPERATION_SIZE_LONGWORD; /* Yup, this isn't a typo. */ 106 | break; 107 | 108 | case 0x3000: 109 | operation_size = OPERATION_SIZE_WORD; 110 | break; 111 | } 112 | 113 | break; 114 | 115 | case INSTRUCTION_EXT: 116 | operation_size = (opcode->raw & 0x0040) != 0 ? OPERATION_SIZE_LONGWORD : OPERATION_SIZE_WORD; 117 | break; 118 | 119 | case INSTRUCTION_ORI: 120 | case INSTRUCTION_ANDI: 121 | case INSTRUCTION_SUBI: 122 | case INSTRUCTION_ADDI: 123 | case INSTRUCTION_EORI: 124 | case INSTRUCTION_CMPI: 125 | case INSTRUCTION_NEGX: 126 | case INSTRUCTION_CLR: 127 | case INSTRUCTION_NEG: 128 | case INSTRUCTION_NOT: 129 | case INSTRUCTION_TST: 130 | case INSTRUCTION_OR: 131 | case INSTRUCTION_SUB: 132 | case INSTRUCTION_SUBX: 133 | case INSTRUCTION_EOR: 134 | case INSTRUCTION_CMPM: 135 | case INSTRUCTION_CMP: 136 | case INSTRUCTION_AND: 137 | case INSTRUCTION_ADD: 138 | case INSTRUCTION_ADDQ: 139 | case INSTRUCTION_SUBQ: 140 | case INSTRUCTION_ADDX: 141 | case INSTRUCTION_ASD_REGISTER: 142 | case INSTRUCTION_LSD_REGISTER: 143 | case INSTRUCTION_ROXD_REGISTER: 144 | case INSTRUCTION_ROD_REGISTER: 145 | /* Standard. */ 146 | switch (1 << opcode->bits_6_and_7) 147 | { 148 | case 1: 149 | operation_size = OPERATION_SIZE_BYTE; 150 | break; 151 | 152 | case 2: 153 | operation_size = OPERATION_SIZE_WORD; 154 | break; 155 | 156 | case 4: 157 | operation_size = OPERATION_SIZE_LONGWORD; 158 | break; 159 | } 160 | 161 | break; 162 | 163 | case INSTRUCTION_BRA_SHORT: 164 | case INSTRUCTION_BSR_SHORT: 165 | case INSTRUCTION_BCC_SHORT: 166 | operation_size = OPERATION_SIZE_SHORT; 167 | break; 168 | 169 | case INSTRUCTION_MOVEP: 170 | case INSTRUCTION_MOVEM: 171 | operation_size = (opcode->bits_6_and_7 & 1) != 0 ? OPERATION_SIZE_LONGWORD : OPERATION_SIZE_WORD; 172 | break; 173 | 174 | case INSTRUCTION_PEA: 175 | case INSTRUCTION_ILLEGAL: 176 | case INSTRUCTION_TRAP: 177 | case INSTRUCTION_UNLK: 178 | case INSTRUCTION_RESET: 179 | case INSTRUCTION_NOP: 180 | case INSTRUCTION_RTE: 181 | case INSTRUCTION_RTS: 182 | case INSTRUCTION_TRAPV: 183 | case INSTRUCTION_RTR: 184 | case INSTRUCTION_JSR: 185 | case INSTRUCTION_JMP: 186 | case INSTRUCTION_EXG: 187 | case INSTRUCTION_UNIMPLEMENTED_1: 188 | case INSTRUCTION_UNIMPLEMENTED_2: 189 | /* Doesn't have a size. */ 190 | break; 191 | } 192 | 193 | return operation_size; 194 | } 195 | 196 | #define SET_OPERAND(OPERATION_SIZE, ADDRESS_MODE, OPERAND_ADDRESS_MODE_REGISTER)\ 197 | do\ 198 | {\ 199 | OPERAND.operation_size = OPERATION_SIZE;\ 200 | OPERAND.address_mode = ADDRESS_MODE;\ 201 | OPERAND.address_mode_register = OPERAND_ADDRESS_MODE_REGISTER;\ 202 | } while(0) 203 | 204 | #define OPERAND decoded_opcode->operands[0] 205 | 206 | static void GetSourceOperand(DecodedOpcode* const decoded_opcode, const SplitOpcode* const opcode) 207 | { 208 | /* Obtain source value. */ 209 | switch (decoded_opcode->instruction) 210 | { 211 | case INSTRUCTION_ORI_TO_CCR: 212 | case INSTRUCTION_ORI_TO_SR: 213 | case INSTRUCTION_ORI: 214 | case INSTRUCTION_ANDI_TO_CCR: 215 | case INSTRUCTION_ANDI_TO_SR: 216 | case INSTRUCTION_ANDI: 217 | case INSTRUCTION_SUBI: 218 | case INSTRUCTION_ADDI: 219 | case INSTRUCTION_EORI_TO_CCR: 220 | case INSTRUCTION_EORI_TO_SR: 221 | case INSTRUCTION_EORI: 222 | case INSTRUCTION_CMPI: 223 | case INSTRUCTION_LINK: 224 | case INSTRUCTION_STOP: 225 | /* Immediate value (any size). */ 226 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_SPECIAL, OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE); 227 | break; 228 | 229 | case INSTRUCTION_BTST_DYNAMIC: 230 | case INSTRUCTION_BCHG_DYNAMIC: 231 | case INSTRUCTION_BCLR_DYNAMIC: 232 | case INSTRUCTION_BSET_DYNAMIC: 233 | case INSTRUCTION_EOR: 234 | /* Secondary data register. */ 235 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 236 | break; 237 | 238 | case INSTRUCTION_BTST_STATIC: 239 | case INSTRUCTION_BCHG_STATIC: 240 | case INSTRUCTION_BCLR_STATIC: 241 | case INSTRUCTION_BSET_STATIC: 242 | /* Immediate value (byte). */ 243 | SET_OPERAND(OPERATION_SIZE_BYTE, OPERAND_ADDRESS_MODE_SPECIAL, OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE); 244 | break; 245 | 246 | case INSTRUCTION_PEA: 247 | case INSTRUCTION_JSR: 248 | case INSTRUCTION_JMP: 249 | case INSTRUCTION_LEA: 250 | /* Memory address */ 251 | SET_OPERAND(OPERATION_SIZE_NONE, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); /* 0 is a special value that means to obtain the address rather than the data at that address. */ 252 | break; 253 | 254 | case INSTRUCTION_MOVE_FROM_SR: 255 | OPERAND.address_mode = OPERAND_ADDRESS_MODE_STATUS_REGISTER; 256 | break; 257 | 258 | case INSTRUCTION_TRAP: 259 | SET_OPERAND(OPERATION_SIZE_WORD, OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE, opcode->raw & 0xF); 260 | break; 261 | 262 | case INSTRUCTION_BRA_WORD: 263 | case INSTRUCTION_BSR_WORD: 264 | case INSTRUCTION_BCC_WORD: 265 | /* Immediate value (word). */ 266 | SET_OPERAND(OPERATION_SIZE_WORD, OPERAND_ADDRESS_MODE_SPECIAL, OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE_ADDRESS); 267 | break; 268 | 269 | case INSTRUCTION_SBCD: 270 | case INSTRUCTION_ABCD: 271 | case INSTRUCTION_SUBX: 272 | case INSTRUCTION_ADDX: 273 | SET_OPERAND(decoded_opcode->size, (opcode->raw & 0x0008) != 0 ? OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT : OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->primary_register); 274 | break; 275 | 276 | case INSTRUCTION_OR: 277 | case INSTRUCTION_SUB: 278 | case INSTRUCTION_AND: 279 | case INSTRUCTION_ADD: 280 | /* Primary address mode or secondary data register, based on direction bit. */ 281 | if (opcode->bit_8) 282 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 283 | else 284 | SET_OPERAND(decoded_opcode->size, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); 285 | 286 | break; 287 | 288 | case INSTRUCTION_CMPM: 289 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT, opcode->primary_register); 290 | break; 291 | 292 | case INSTRUCTION_MOVEA: 293 | case INSTRUCTION_MOVE: 294 | case INSTRUCTION_MOVE_TO_CCR: 295 | case INSTRUCTION_MOVE_TO_SR: 296 | case INSTRUCTION_CHK: 297 | case INSTRUCTION_CMP: 298 | case INSTRUCTION_TST: 299 | case INSTRUCTION_SUBA: 300 | case INSTRUCTION_CMPA: 301 | case INSTRUCTION_ADDA: 302 | /* Primary address mode. */ 303 | SET_OPERAND(decoded_opcode->size, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); 304 | break; 305 | 306 | case INSTRUCTION_DIVU: 307 | case INSTRUCTION_DIVS: 308 | case INSTRUCTION_MULU: 309 | case INSTRUCTION_MULS: 310 | /* Primary address mode, hardcoded to word-size. */ 311 | SET_OPERAND(OPERATION_SIZE_WORD, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); 312 | break; 313 | 314 | case INSTRUCTION_BRA_SHORT: 315 | case INSTRUCTION_BSR_SHORT: 316 | case INSTRUCTION_BCC_SHORT: 317 | SET_OPERAND(OPERATION_SIZE_BYTE, OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE_ADDRESS, CC_SIGN_EXTEND_UINT(7, opcode->raw)); 318 | break; 319 | 320 | case INSTRUCTION_MOVEQ: 321 | SET_OPERAND(OPERATION_SIZE_BYTE, OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE, CC_SIGN_EXTEND_UINT(7, opcode->raw)); 322 | break; 323 | 324 | case INSTRUCTION_DBCC: 325 | SET_OPERAND(OPERATION_SIZE_WORD, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->primary_register); 326 | break; 327 | 328 | case INSTRUCTION_ADDAQ: 329 | case INSTRUCTION_SUBAQ: 330 | case INSTRUCTION_ADDQ: 331 | case INSTRUCTION_SUBQ: 332 | case INSTRUCTION_ASD_REGISTER: 333 | case INSTRUCTION_LSD_REGISTER: 334 | case INSTRUCTION_ROXD_REGISTER: 335 | case INSTRUCTION_ROD_REGISTER: 336 | SET_OPERAND(OPERATION_SIZE_WORD, OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE, ((opcode->secondary_register - 1u) & 7u) + 1u); /* A little math trick to turn 0 into 8 */ 337 | break; 338 | 339 | case INSTRUCTION_MOVE_USP: 340 | if ((opcode->raw & 8) != 0) 341 | SET_OPERAND(OPERATION_SIZE_LONGWORD, OPERAND_ADDRESS_MODE_USER_STACK_POINTER, 0); 342 | else 343 | SET_OPERAND(OPERATION_SIZE_LONGWORD, OPERAND_ADDRESS_MODE_ADDRESS_REGISTER, opcode->primary_register); 344 | 345 | break; 346 | 347 | case INSTRUCTION_MOVEP: 348 | if ((opcode->bits_6_and_7 & 2) != 0) 349 | SET_OPERAND(OPERATION_SIZE_NONE, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 350 | else 351 | SET_OPERAND(OPERATION_SIZE_NONE, OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT, opcode->primary_register); 352 | 353 | break; 354 | 355 | case INSTRUCTION_MOVEM: 356 | if ((opcode->raw & 0x0400) != 0) 357 | { 358 | SET_OPERAND(OPERATION_SIZE_NONE, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); /* OPERATION_SIZE_NONE is a special value that means to obtain the address rather than the data at that address. */ 359 | } 360 | else 361 | { 362 | if (opcode->primary_address_mode == ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT) 363 | SET_OPERAND(OPERATION_SIZE_WORD, OPERAND_ADDRESS_MODE_SPECIAL, OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST_REVERSED); 364 | else 365 | SET_OPERAND(OPERATION_SIZE_WORD, OPERAND_ADDRESS_MODE_SPECIAL, OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST); 366 | } 367 | 368 | break; 369 | 370 | case INSTRUCTION_NEGX: 371 | case INSTRUCTION_CLR: 372 | case INSTRUCTION_NEG: 373 | case INSTRUCTION_NOT: 374 | case INSTRUCTION_EXT: 375 | case INSTRUCTION_NBCD: 376 | case INSTRUCTION_SWAP: 377 | case INSTRUCTION_ILLEGAL: 378 | case INSTRUCTION_TAS: 379 | case INSTRUCTION_UNLK: 380 | case INSTRUCTION_RESET: 381 | case INSTRUCTION_NOP: 382 | case INSTRUCTION_RTE: 383 | case INSTRUCTION_RTS: 384 | case INSTRUCTION_TRAPV: 385 | case INSTRUCTION_RTR: 386 | case INSTRUCTION_SCC: 387 | case INSTRUCTION_EXG: 388 | case INSTRUCTION_ASD_MEMORY: 389 | case INSTRUCTION_LSD_MEMORY: 390 | case INSTRUCTION_ROXD_MEMORY: 391 | case INSTRUCTION_ROD_MEMORY: 392 | case INSTRUCTION_UNIMPLEMENTED_1: 393 | case INSTRUCTION_UNIMPLEMENTED_2: 394 | /* Doesn't have a source address mode to decode. */ 395 | OPERAND.address_mode = OPERAND_ADDRESS_MODE_NONE; 396 | break; 397 | } 398 | } 399 | 400 | #undef OPERAND 401 | #define OPERAND decoded_opcode->operands[1] 402 | 403 | static void GetDestinationOperand(DecodedOpcode* const decoded_opcode, const SplitOpcode* const opcode) 404 | { 405 | /* Decode destination address mode */ 406 | switch (decoded_opcode->instruction) 407 | { 408 | case INSTRUCTION_EXT: 409 | case INSTRUCTION_SWAP: 410 | case INSTRUCTION_ASD_REGISTER: 411 | case INSTRUCTION_LSD_REGISTER: 412 | case INSTRUCTION_ROXD_REGISTER: 413 | case INSTRUCTION_ROD_REGISTER: 414 | /* Data register (primary) */ 415 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->primary_register); 416 | break; 417 | 418 | case INSTRUCTION_MOVEQ: 419 | case INSTRUCTION_CMP: 420 | /* Data register (secondary) */ 421 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 422 | break; 423 | 424 | case INSTRUCTION_DIVU: 425 | case INSTRUCTION_DIVS: 426 | case INSTRUCTION_MULU: 427 | case INSTRUCTION_MULS: 428 | /* Full secondary data register */ 429 | SET_OPERAND(OPERATION_SIZE_LONGWORD, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 430 | break; 431 | 432 | case INSTRUCTION_MOVE: 433 | /* Secondary address mode */ 434 | SET_OPERAND(decoded_opcode->size, (OperandAddressMode)opcode->secondary_address_mode, opcode->secondary_register); 435 | break; 436 | 437 | case INSTRUCTION_SBCD: 438 | case INSTRUCTION_SUBX: 439 | case INSTRUCTION_ABCD: 440 | case INSTRUCTION_ADDX: 441 | SET_OPERAND(decoded_opcode->size, (opcode->raw & 0x0008) != 0 ? OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT : OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 442 | break; 443 | 444 | case INSTRUCTION_OR: 445 | case INSTRUCTION_SUB: 446 | case INSTRUCTION_AND: 447 | case INSTRUCTION_ADD: 448 | /* Primary address mode or secondary data register, based on direction bit */ 449 | if (opcode->bit_8) 450 | SET_OPERAND(decoded_opcode->size, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); 451 | else 452 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 453 | 454 | break; 455 | 456 | case INSTRUCTION_LEA: 457 | case INSTRUCTION_SUBA: 458 | case INSTRUCTION_CMPA: 459 | case INSTRUCTION_ADDA: 460 | case INSTRUCTION_MOVEA: 461 | /* Full secondary address register */ 462 | SET_OPERAND(OPERATION_SIZE_LONGWORD, OPERAND_ADDRESS_MODE_ADDRESS_REGISTER, opcode->secondary_register); 463 | break; 464 | 465 | case INSTRUCTION_CMPM: 466 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT, opcode->secondary_register); 467 | break; 468 | 469 | case INSTRUCTION_ORI: 470 | case INSTRUCTION_ANDI: 471 | case INSTRUCTION_SUBI: 472 | case INSTRUCTION_ADDI: 473 | case INSTRUCTION_EORI: 474 | case INSTRUCTION_CMPI: 475 | case INSTRUCTION_BTST_STATIC: 476 | case INSTRUCTION_BCHG_STATIC: 477 | case INSTRUCTION_BCLR_STATIC: 478 | case INSTRUCTION_BSET_STATIC: 479 | case INSTRUCTION_BTST_DYNAMIC: 480 | case INSTRUCTION_BCHG_DYNAMIC: 481 | case INSTRUCTION_BCLR_DYNAMIC: 482 | case INSTRUCTION_BSET_DYNAMIC: 483 | case INSTRUCTION_NEGX: 484 | case INSTRUCTION_NEG: 485 | case INSTRUCTION_NOT: 486 | case INSTRUCTION_NBCD: 487 | case INSTRUCTION_TAS: 488 | case INSTRUCTION_MOVE_FROM_SR: 489 | case INSTRUCTION_CLR: 490 | case INSTRUCTION_ADDAQ: 491 | case INSTRUCTION_SUBAQ: 492 | case INSTRUCTION_ADDQ: 493 | case INSTRUCTION_SUBQ: 494 | case INSTRUCTION_SCC: 495 | case INSTRUCTION_EOR: 496 | case INSTRUCTION_ASD_MEMORY: 497 | case INSTRUCTION_LSD_MEMORY: 498 | case INSTRUCTION_ROXD_MEMORY: 499 | case INSTRUCTION_ROD_MEMORY: 500 | /* Using primary address mode */ 501 | SET_OPERAND(decoded_opcode->size, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); 502 | break; 503 | 504 | case INSTRUCTION_ORI_TO_CCR: 505 | case INSTRUCTION_ANDI_TO_CCR: 506 | case INSTRUCTION_EORI_TO_CCR: 507 | case INSTRUCTION_MOVE_TO_CCR: 508 | OPERAND.address_mode = OPERAND_ADDRESS_MODE_CONDITION_CODE_REGISTER; 509 | break; 510 | 511 | case INSTRUCTION_ORI_TO_SR: 512 | case INSTRUCTION_ANDI_TO_SR: 513 | case INSTRUCTION_EORI_TO_SR: 514 | case INSTRUCTION_MOVE_TO_SR: 515 | OPERAND.address_mode = OPERAND_ADDRESS_MODE_STATUS_REGISTER; 516 | break; 517 | 518 | case INSTRUCTION_MOVEM: 519 | if ((opcode->raw & 0x0400) != 0) 520 | SET_OPERAND(OPERATION_SIZE_WORD, OPERAND_ADDRESS_MODE_SPECIAL, OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST); 521 | else 522 | SET_OPERAND(OPERATION_SIZE_NONE, (OperandAddressMode)opcode->primary_address_mode, opcode->primary_register); /* OPERATION_SIZE_NONE is a special value that means to obtain the address rather than the data at that address. */ 523 | 524 | break; 525 | 526 | case INSTRUCTION_MOVEP: 527 | if ((opcode->bits_6_and_7 & 2) != 0) 528 | SET_OPERAND(OPERATION_SIZE_NONE, OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT, opcode->primary_register); 529 | else 530 | SET_OPERAND(OPERATION_SIZE_NONE, OPERAND_ADDRESS_MODE_DATA_REGISTER, opcode->secondary_register); 531 | 532 | break; 533 | 534 | case INSTRUCTION_DBCC: 535 | /* Immediate value (any size). */ 536 | SET_OPERAND(decoded_opcode->size, OPERAND_ADDRESS_MODE_SPECIAL, OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE_ADDRESS); 537 | break; 538 | 539 | case INSTRUCTION_MOVE_USP: 540 | if ((opcode->raw & 8) != 0) 541 | SET_OPERAND(OPERATION_SIZE_LONGWORD, OPERAND_ADDRESS_MODE_ADDRESS_REGISTER, opcode->primary_register); 542 | else 543 | SET_OPERAND(OPERATION_SIZE_LONGWORD, OPERAND_ADDRESS_MODE_USER_STACK_POINTER, 0); 544 | 545 | break; 546 | 547 | case INSTRUCTION_PEA: 548 | case INSTRUCTION_ILLEGAL: 549 | case INSTRUCTION_TRAP: 550 | case INSTRUCTION_LINK: 551 | case INSTRUCTION_UNLK: 552 | case INSTRUCTION_RESET: 553 | case INSTRUCTION_NOP: 554 | case INSTRUCTION_STOP: 555 | case INSTRUCTION_RTE: 556 | case INSTRUCTION_RTS: 557 | case INSTRUCTION_TRAPV: 558 | case INSTRUCTION_RTR: 559 | case INSTRUCTION_JSR: 560 | case INSTRUCTION_JMP: 561 | case INSTRUCTION_CHK: 562 | case INSTRUCTION_BRA_SHORT: 563 | case INSTRUCTION_BRA_WORD: 564 | case INSTRUCTION_BSR_SHORT: 565 | case INSTRUCTION_BSR_WORD: 566 | case INSTRUCTION_BCC_SHORT: 567 | case INSTRUCTION_BCC_WORD: 568 | case INSTRUCTION_EXG: 569 | case INSTRUCTION_TST: 570 | case INSTRUCTION_UNIMPLEMENTED_1: 571 | case INSTRUCTION_UNIMPLEMENTED_2: 572 | /* Doesn't have a destination address mode to decode. */ 573 | OPERAND.address_mode = OPERAND_ADDRESS_MODE_NONE; 574 | break; 575 | } 576 | } 577 | 578 | #undef OPERAND 579 | #undef SET_OPERAND 580 | 581 | void DecodeOpcodeAndOperands(DecodedOpcode* const decoded_opcode, SplitOpcode* const split_opcode, const unsigned int opcode) 582 | { 583 | decoded_opcode->instruction = DecodeOpcode(split_opcode, opcode); 584 | decoded_opcode->size = GetSize(decoded_opcode->instruction, split_opcode); 585 | GetSourceOperand(decoded_opcode, split_opcode); 586 | GetDestinationOperand(decoded_opcode, split_opcode); 587 | } 588 | -------------------------------------------------------------------------------- /disassembler/opcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INCLUDE_GUARD_707770EC_8F3D_4A9D_A5CD_FA706BC21B56 20 | #define INCLUDE_GUARD_707770EC_8F3D_4A9D_A5CD_FA706BC21B56 21 | 22 | #include "../common/instruction.h" 23 | #include "../common/opcode.h" 24 | 25 | typedef enum OperandAddressMode 26 | { 27 | OPERAND_ADDRESS_MODE_DATA_REGISTER = ADDRESS_MODE_DATA_REGISTER, 28 | OPERAND_ADDRESS_MODE_ADDRESS_REGISTER = ADDRESS_MODE_ADDRESS_REGISTER, 29 | OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT = ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT, 30 | OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT = ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_POSTINCREMENT, 31 | OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT = ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT, 32 | OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT = ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT, 33 | OPERAND_ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_INDEX = ADDRESS_MODE_ADDRESS_REGISTER_INDIRECT_WITH_INDEX, 34 | OPERAND_ADDRESS_MODE_SPECIAL = ADDRESS_MODE_SPECIAL, 35 | /* Custom - These were added for uniformity, but never actually occur in M68k opcodes. */ 36 | OPERAND_ADDRESS_MODE_STATUS_REGISTER = 8, 37 | OPERAND_ADDRESS_MODE_CONDITION_CODE_REGISTER = 9, 38 | OPERAND_ADDRESS_MODE_NONE = 10, 39 | OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE = 11, 40 | OPERAND_ADDRESS_MODE_EMBEDDED_IMMEDIATE_ADDRESS = 12, 41 | OPERAND_ADDRESS_MODE_USER_STACK_POINTER = 13 42 | } OperandAddressMode; 43 | 44 | typedef enum OperandAddressModeSpecial 45 | { 46 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_SHORT = ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_SHORT, 47 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_LONG = ADDRESS_MODE_REGISTER_SPECIAL_ABSOLUTE_LONG, 48 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_DISPLACEMENT = ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_DISPLACEMENT, 49 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_INDEX = ADDRESS_MODE_REGISTER_SPECIAL_PROGRAM_COUNTER_WITH_INDEX, 50 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE = ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE, 51 | /* Custom - These were added for uniformity, but never actually occur in M68k opcodes. */ 52 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_IMMEDIATE_ADDRESS = 5, 53 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST = 6, 54 | OPERAND_ADDRESS_MODE_REGISTER_SPECIAL_REGISTER_LIST_REVERSED = 7 55 | } OperandAddressModeSpecial; 56 | 57 | typedef enum OperationSize 58 | { 59 | OPERATION_SIZE_BYTE, 60 | OPERATION_SIZE_SHORT, 61 | OPERATION_SIZE_WORD, 62 | OPERATION_SIZE_LONGWORD, 63 | OPERATION_SIZE_NONE 64 | } OperationSize; 65 | 66 | typedef struct Operand 67 | { 68 | OperationSize operation_size; 69 | OperandAddressMode address_mode; 70 | unsigned int address_mode_register; 71 | } Operand; 72 | 73 | typedef struct DecodedOpcode 74 | { 75 | Instruction instruction; 76 | OperationSize size; 77 | Operand operands[2]; 78 | } DecodedOpcode; 79 | 80 | void DecodeOpcodeAndOperands(DecodedOpcode *decoded_opcode, SplitOpcode *split_opcode, unsigned int opcode); 81 | 82 | #endif /* INCLUDE_GUARD_707770EC_8F3D_4A9D_A5CD_FA706BC21B56 */ 83 | -------------------------------------------------------------------------------- /interpreter/clown68000.h: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INCLUDE_GUARD_8BAB17D5_7D64_4CA2_998B_F3F43D7FD80F 20 | #define INCLUDE_GUARD_8BAB17D5_7D64_4CA2_998B_F3F43D7FD80F 21 | 22 | #include 23 | 24 | #include "../common/clowncommon/clowncommon.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | typedef struct Clown68000_State 31 | { 32 | cc_u32l data_registers[8]; 33 | cc_u32l address_registers[8]; 34 | cc_u32l supervisor_stack_pointer; 35 | cc_u32l user_stack_pointer; 36 | cc_u32l program_counter; 37 | cc_u16l status_register; 38 | cc_u16l instruction_register; 39 | cc_bool halted, stopped; 40 | cc_u8l pending_interrupt; 41 | } Clown68000_State; 42 | 43 | typedef struct Clown68000_ReadWriteCallbacks 44 | { 45 | cc_u16f (*read_callback)(const void *user_data, cc_u32f address, cc_bool do_high_byte, cc_bool do_low_byte); 46 | void (*write_callback)(const void *user_data, cc_u32f address, cc_bool do_high_byte, cc_bool do_low_byte, cc_u16f value); 47 | const void *user_data; 48 | } Clown68000_ReadWriteCallbacks; 49 | 50 | void Clown68000_SetErrorCallback(void (*error_callback)(void *user_data, const char *format, va_list arg), const void *user_data); 51 | void Clown68000_Reset(Clown68000_State *state, const Clown68000_ReadWriteCallbacks *callbacks); 52 | void Clown68000_Interrupt(Clown68000_State *state, cc_u16f level); 53 | cc_u8f Clown68000_DoCycle(Clown68000_State *state, const Clown68000_ReadWriteCallbacks *callbacks); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* INCLUDE_GUARD_8BAB17D5_7D64_4CA2_998B_F3F43D7FD80F */ 60 | -------------------------------------------------------------------------------- /interpreter/microcode-generator/emit-instructions.c: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "emit-instructions.h" 20 | 21 | #include 22 | 23 | #include "emit.h" 24 | #include "instruction-properties.h" 25 | 26 | void EmitInstructionSupervisorCheck(const Instruction instruction) 27 | { 28 | if (Instruction_IsPrivileged(instruction)) 29 | { 30 | Emit("/* Only allow this instruction in supervisor mode. */"); 31 | Emit("SupervisorCheck(&stuff);"); 32 | Emit(""); 33 | } 34 | } 35 | 36 | void EmitInstructionSize(const Instruction instruction) 37 | { 38 | const InstructionSize size = Instruction_GetSize(instruction); 39 | 40 | if (size != INSTRUCTION_SIZE_NONE) 41 | { 42 | switch (Instruction_GetSize(instruction)) 43 | { 44 | case INSTRUCTION_SIZE_BYTE: 45 | /* Hardcoded to a byte. */ 46 | Emit("SetSize_Byte(&stuff);"); 47 | break; 48 | 49 | case INSTRUCTION_SIZE_WORD: 50 | /* Hardcoded to a word. */ 51 | Emit("SetSize_Word(&stuff);"); 52 | break; 53 | 54 | case INSTRUCTION_SIZE_LONGWORD: 55 | /* Hardcoded to a longword. */ 56 | Emit("SetSize_Longword(&stuff);"); 57 | break; 58 | 59 | case INSTRUCTION_SIZE_LONGWORD_REGISTER_BYTE_MEMORY: 60 | /* 4 if register - 1 if memory. */ 61 | Emit("SetSize_LongwordRegisterByteMemory(&stuff);"); 62 | break; 63 | 64 | case INSTRUCTION_SIZE_MOVE: 65 | /* Derived from an odd bitfield. */ 66 | Emit("SetSize_Move(&stuff);"); 67 | break; 68 | 69 | case INSTRUCTION_SIZE_EXT: 70 | Emit("SetSize_Ext(&stuff);"); 71 | break; 72 | 73 | case INSTRUCTION_SIZE_STANDARD: 74 | /* Standard. */ 75 | Emit("SetSize_Standard(&stuff);"); 76 | break; 77 | 78 | case INSTRUCTION_SIZE_NONE: 79 | /* Doesn't have a size. */ 80 | break; 81 | } 82 | 83 | Emit("SetMSBBitIndex(&stuff);"); 84 | Emit(""); 85 | } 86 | } 87 | 88 | void EmitInstructionSourceAddressMode(const Instruction instruction) 89 | { 90 | if (Instruction_IsSourceOperandRead(instruction)) 91 | { 92 | Emit("/* Decode source address mode. */"); 93 | 94 | switch (Instruction_GetSourceOperand(instruction)) 95 | { 96 | case INSTRUCTION_SOURCE_IMMEDIATE_DATA: 97 | /* Immediate value (any size). */ 98 | Emit("DecodeSource_ImmediateData(&stuff);"); 99 | break; 100 | 101 | case INSTRUCTION_SOURCE_DATA_REGISTER_SECONDARY: 102 | /* Secondary data register. */ 103 | Emit("DecodeSource_DataRegisterSecondary(&stuff);"); 104 | break; 105 | 106 | case INSTRUCTION_SOURCE_IMMEDIATE_DATA_BYTE: 107 | /* Immediate value (byte). */ 108 | Emit("DecodeSource_ImmediateDataByte(&stuff);"); 109 | break; 110 | 111 | case INSTRUCTION_SOURCE_MEMORY_ADDRESS_PRIMARY: 112 | /* Memory address */ 113 | Emit("DecodeSource_MemoryAddressPrimary(&stuff);"); 114 | break; 115 | 116 | case INSTRUCTION_SOURCE_STATUS_REGISTER: 117 | Emit("DecodeSource_StatusRegister(&stuff);"); 118 | break; 119 | 120 | case INSTRUCTION_SOURCE_IMMEDIATE_DATA_WORD: 121 | /* Immediate value (word). */ 122 | Emit("DecodeSource_ImmediateDataWord(&stuff);"); 123 | break; 124 | 125 | case INSTRUCTION_SOURCE_BCD_X: 126 | Emit("DecodeSource_BCDX(&stuff);"); 127 | break; 128 | 129 | case INSTRUCTION_SOURCE_DATA_REGISTER_SECONDARY_OR_PRIMARY_ADDRESS_MODE: 130 | /* Primary address mode or secondary data register, based on direction bit. */ 131 | Emit("DecodeSource_DataRegisterSecondaryOrPrimaryAddressMode(&stuff);"); 132 | break; 133 | 134 | case INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE_SIZED: 135 | /* Word or longword based on bit 8. */ 136 | Emit("DecodeSource_PrimaryAddressModeSized(&stuff);"); 137 | break; 138 | 139 | case INSTRUCTION_SOURCE_ADDRESS_REGISTER_PRIMARY_POSTINCREMENT: 140 | Emit("DecodeSource_AddressRegisterPrimaryPostIncrement(&stuff);"); 141 | break; 142 | 143 | case INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE: 144 | /* Primary address mode. */ 145 | Emit("DecodeSource_PrimaryAddressMode(&stuff);"); 146 | break; 147 | 148 | case INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE_WORD: 149 | /* Primary address mode, hardcoded to word-size. */ 150 | Emit("DecodeSource_PrimaryAddressModeWord(&stuff);"); 151 | break; 152 | 153 | case INSTRUCTION_SOURCE_NONE: 154 | /* Doesn't have a source address mode to decode. */ 155 | break; 156 | } 157 | 158 | Emit(""); 159 | } 160 | } 161 | 162 | void EmitInstructionDestinationAddressMode(const Instruction instruction) 163 | { 164 | if (Instruction_IsDestinationOperandRead(instruction) || Instruction_IsDestinationOperandWritten(instruction)) 165 | { 166 | Emit("/* Decode destination address mode. */"); 167 | 168 | switch (Instruction_GetDestinationOperand(instruction)) 169 | { 170 | case INSTRUCTION_DESTINATION_DATA_REGISTER_PRIMARY: 171 | /* Data register (primary) */ 172 | Emit("DecodeDestination_DataRegisterPrimary(&stuff);"); 173 | break; 174 | 175 | case INSTRUCTION_DESTINATION_DATA_REGISTER_SECONDARY: 176 | /* Data register (secondary) */ 177 | Emit("DecodeDestination_DataRegisterSecondary(&stuff);"); 178 | break; 179 | 180 | case INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY: 181 | /* Address register (secondary) */ 182 | Emit("DecodeDestination_AddressRegisterSecondary(&stuff);"); 183 | break; 184 | 185 | case INSTRUCTION_DESTINATION_SECONDARY_ADDRESS_MODE: 186 | /* Secondary address mode */ 187 | Emit("DecodeDestination_SecondaryAddressMode(&stuff);"); 188 | break; 189 | 190 | case INSTRUCTION_DESTINATION_BCD_X: 191 | Emit("DecodeDestination_BCDX(&stuff);"); 192 | break; 193 | 194 | case INSTRUCTION_DESTINATION_DATA_REGISTER_SECONDARY_OR_PRIMARY_ADDRESS_MODE: 195 | /* Primary address mode or secondary data register, based on direction bit */ 196 | Emit("DecodeDestination_DataRegisterSecondaryOrPrimaryAddressMode(&stuff);"); 197 | break; 198 | 199 | case INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY_FULL: 200 | /* Full secondary address register */ 201 | Emit("DecodeDestination_AddressRegisterSecondaryFull(&stuff);"); 202 | break; 203 | 204 | case INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY_POSTINCREMENT: 205 | Emit("DecodeDestination_AddressRegisterSecondaryPostIncrement(&stuff);"); 206 | break; 207 | 208 | case INSTRUCTION_DESTINATION_PRIMARY_ADDRESS_MODE: 209 | /* Using primary address mode */ 210 | Emit("DecodeDestination_PrimaryAddressMode(&stuff);"); 211 | break; 212 | 213 | case INSTRUCTION_DESTINATION_CONDITION_CODE_REGISTER: 214 | Emit("DecodeDestination_ConditionCodeRegister(&stuff);"); 215 | break; 216 | 217 | case INSTRUCTION_DESTINATION_STATUS_REGISTER: 218 | Emit("DecodeDestination_StatusRegister(&stuff);"); 219 | break; 220 | 221 | case INSTRUCTION_DESTINATION_MOVEM: 222 | /* Memory address */ 223 | Emit("DecodeDestination_MOVEM(&stuff);"); 224 | break; 225 | 226 | case INSTRUCTION_DESTINATION_MOVEP: 227 | /* Memory address */ 228 | Emit("DecodeDestination_MOVEP(&stuff);"); 229 | break; 230 | 231 | case INSTRUCTION_DESTINATION_NONE: 232 | /* Doesn't have a destination address mode to decode. */ 233 | break; 234 | } 235 | 236 | Emit(""); 237 | } 238 | } 239 | 240 | void EmitInstructionReadSourceOperand(const Instruction instruction) 241 | { 242 | if (Instruction_IsSourceOperandRead(instruction)) 243 | { 244 | Emit("/* Read source operand. */"); 245 | Emit("ReadSource(&stuff);"); 246 | Emit(""); 247 | } 248 | } 249 | 250 | void EmitInstructionReadDestinationOperand(const Instruction instruction) 251 | { 252 | if (Instruction_IsDestinationOperandRead(instruction)) 253 | { 254 | Emit("/* Read destination operand. */"); 255 | Emit("ReadDestination(&stuff);"); 256 | Emit(""); 257 | } 258 | } 259 | 260 | void EmitInstructionAction(const Instruction instruction) 261 | { 262 | Emit("/* Do the actual instruction. */"); 263 | 264 | switch (Instruction_GetAction(instruction)) 265 | { 266 | case INSTRUCTION_ACTION_OR: 267 | Emit("Action_OR(&stuff);"); 268 | break; 269 | 270 | case INSTRUCTION_ACTION_AND: 271 | Emit("Action_AND(&stuff);"); 272 | break; 273 | 274 | case INSTRUCTION_ACTION_CMPA: 275 | Emit("Action_CMPA(&stuff);"); 276 | break; 277 | 278 | case INSTRUCTION_ACTION_CMP: 279 | Emit("Action_CMP(&stuff);"); 280 | break; 281 | 282 | case INSTRUCTION_ACTION_CMPM: 283 | Emit("Action_CMPM(&stuff);"); 284 | break; 285 | 286 | case INSTRUCTION_ACTION_CMPI: 287 | Emit("Action_CMPI(&stuff);"); 288 | break; 289 | 290 | case INSTRUCTION_ACTION_SUBA: 291 | Emit("Action_SUBA(&stuff);"); 292 | break; 293 | 294 | case INSTRUCTION_ACTION_SUBQ: 295 | Emit("Action_SUBQ(&stuff);"); 296 | break; 297 | 298 | case INSTRUCTION_ACTION_SUB: 299 | Emit("Action_SUB(&stuff);"); 300 | break; 301 | 302 | case INSTRUCTION_ACTION_ADDA: 303 | Emit("Action_ADDA(&stuff);"); 304 | break; 305 | 306 | case INSTRUCTION_ACTION_ADDQ: 307 | Emit("Action_ADDQ(&stuff);"); 308 | break; 309 | 310 | case INSTRUCTION_ACTION_ADD: 311 | Emit("Action_ADD(&stuff);"); 312 | break; 313 | 314 | case INSTRUCTION_ACTION_EOR: 315 | Emit("Action_EOR(&stuff);"); 316 | break; 317 | 318 | case INSTRUCTION_ACTION_TST: 319 | Emit("Action_TST(&stuff);"); 320 | break; 321 | 322 | case INSTRUCTION_ACTION_BCHG: 323 | Emit("Action_BCHG(&stuff);"); 324 | break; 325 | 326 | case INSTRUCTION_ACTION_BCLR: 327 | Emit("Action_BCLR(&stuff);"); 328 | break; 329 | 330 | case INSTRUCTION_ACTION_BSET: 331 | Emit("Action_BSET(&stuff);"); 332 | break; 333 | 334 | case INSTRUCTION_ACTION_BTST: 335 | Emit("Action_BTST(&stuff);"); 336 | break; 337 | 338 | case INSTRUCTION_ACTION_MOVEP: 339 | Emit("Action_MOVEP(&stuff);"); 340 | break; 341 | 342 | case INSTRUCTION_ACTION_MOVEA: 343 | Emit("Action_MOVEA(&stuff);"); 344 | break; 345 | 346 | case INSTRUCTION_ACTION_MOVE: 347 | Emit("Action_MOVE(&stuff);"); 348 | break; 349 | 350 | case INSTRUCTION_ACTION_LINK: 351 | Emit("Action_LINK(&stuff);"); 352 | break; 353 | 354 | case INSTRUCTION_ACTION_UNLK: 355 | Emit("Action_UNLK(&stuff);"); 356 | break; 357 | 358 | case INSTRUCTION_ACTION_NEGX: 359 | Emit("Action_NEGX(&stuff);"); 360 | break; 361 | 362 | case INSTRUCTION_ACTION_CLR: 363 | Emit("Action_CLR(&stuff);"); 364 | break; 365 | 366 | case INSTRUCTION_ACTION_NEG: 367 | Emit("Action_NEG(&stuff);"); 368 | break; 369 | 370 | case INSTRUCTION_ACTION_NOT: 371 | Emit("Action_NOT(&stuff);"); 372 | break; 373 | 374 | case INSTRUCTION_ACTION_EXT: 375 | Emit("Action_EXT(&stuff);"); 376 | break; 377 | 378 | case INSTRUCTION_ACTION_NBCD: 379 | Emit("Action_NBCD(&stuff);"); 380 | break; 381 | 382 | case INSTRUCTION_ACTION_SWAP: 383 | Emit("Action_SWAP(&stuff);"); 384 | break; 385 | 386 | case INSTRUCTION_ACTION_PEA: 387 | Emit("Action_PEA(&stuff);"); 388 | break; 389 | 390 | case INSTRUCTION_ACTION_ILLEGAL: 391 | Emit("Action_ILLEGAL(&stuff);"); 392 | break; 393 | 394 | case INSTRUCTION_ACTION_TAS: 395 | Emit("Action_TAS(&stuff);"); 396 | break; 397 | 398 | case INSTRUCTION_ACTION_TRAP: 399 | Emit("Action_TRAP(&stuff);"); 400 | break; 401 | 402 | case INSTRUCTION_ACTION_MOVE_USP: 403 | Emit("Action_MOVE_USP(&stuff);"); 404 | break; 405 | 406 | case INSTRUCTION_ACTION_RESET: 407 | Emit("Action_RESET(&stuff);"); 408 | break; 409 | 410 | case INSTRUCTION_ACTION_STOP: 411 | Emit("Action_STOP(&stuff);"); 412 | break; 413 | 414 | case INSTRUCTION_ACTION_RTE: 415 | Emit("Action_RTE(&stuff);"); 416 | break; 417 | 418 | case INSTRUCTION_ACTION_RTS: 419 | Emit("Action_RTS(&stuff);"); 420 | break; 421 | 422 | case INSTRUCTION_ACTION_TRAPV: 423 | Emit("Action_TRAPV(&stuff);"); 424 | break; 425 | 426 | case INSTRUCTION_ACTION_RTR: 427 | Emit("Action_RTR(&stuff);"); 428 | break; 429 | 430 | case INSTRUCTION_ACTION_JSR: 431 | Emit("Action_JSR(&stuff);"); 432 | break; 433 | 434 | case INSTRUCTION_ACTION_JMP: 435 | Emit("Action_JMP(&stuff);"); 436 | break; 437 | 438 | case INSTRUCTION_ACTION_LEA: 439 | Emit("Action_LEA(&stuff);"); 440 | break; 441 | 442 | case INSTRUCTION_ACTION_MOVEM: 443 | Emit("Action_MOVEM(&stuff);"); 444 | break; 445 | 446 | case INSTRUCTION_ACTION_CHK: 447 | Emit("Action_CHK(&stuff);"); 448 | break; 449 | 450 | case INSTRUCTION_ACTION_SCC: 451 | Emit("Action_SCC(&stuff);"); 452 | break; 453 | 454 | case INSTRUCTION_ACTION_DBCC: 455 | Emit("Action_DBCC(&stuff);"); 456 | break; 457 | 458 | case INSTRUCTION_ACTION_BRA_SHORT: 459 | Emit("Action_BRA_SHORT(&stuff);"); 460 | break; 461 | 462 | case INSTRUCTION_ACTION_BRA_WORD: 463 | Emit("Action_BRA_WORD(&stuff);"); 464 | break; 465 | 466 | case INSTRUCTION_ACTION_BSR_SHORT: 467 | Emit("Action_BSR_SHORT(&stuff);"); 468 | break; 469 | 470 | case INSTRUCTION_ACTION_BSR_WORD: 471 | Emit("Action_BSR_WORD(&stuff);"); 472 | break; 473 | 474 | case INSTRUCTION_ACTION_BCC_SHORT: 475 | Emit("Action_BCC_SHORT(&stuff);"); 476 | break; 477 | 478 | case INSTRUCTION_ACTION_BCC_WORD: 479 | Emit("Action_BCC_WORD(&stuff);"); 480 | break; 481 | 482 | case INSTRUCTION_ACTION_MOVEQ: 483 | Emit("Action_MOVEQ(&stuff);"); 484 | break; 485 | 486 | case INSTRUCTION_ACTION_DIVS: 487 | Emit("Action_DIVS(&stuff);"); 488 | break; 489 | 490 | case INSTRUCTION_ACTION_DIVU: 491 | Emit("Action_DIVU(&stuff);"); 492 | break; 493 | 494 | case INSTRUCTION_ACTION_SBCD: 495 | Emit("Action_SBCD(&stuff);"); 496 | break; 497 | 498 | case INSTRUCTION_ACTION_SUBX: 499 | Emit("Action_SUBX(&stuff);"); 500 | break; 501 | 502 | case INSTRUCTION_ACTION_MULS: 503 | Emit("Action_MULS(&stuff);"); 504 | break; 505 | 506 | case INSTRUCTION_ACTION_MULU: 507 | Emit("Action_MULU(&stuff);"); 508 | break; 509 | 510 | case INSTRUCTION_ACTION_ABCD: 511 | Emit("Action_ABCD(&stuff);"); 512 | break; 513 | 514 | case INSTRUCTION_ACTION_EXG: 515 | Emit("Action_EXG(&stuff);"); 516 | break; 517 | 518 | case INSTRUCTION_ACTION_ADDX: 519 | Emit("Action_ADDX(&stuff);"); 520 | break; 521 | 522 | case INSTRUCTION_ACTION_ASD_MEMORY: 523 | Emit("Action_ASD_MEMORY(&stuff);"); 524 | break; 525 | 526 | case INSTRUCTION_ACTION_ASD_REGISTER: 527 | Emit("Action_ASD_REGISTER(&stuff);"); 528 | break; 529 | 530 | case INSTRUCTION_ACTION_LSD_MEMORY: 531 | Emit("Action_LSD_MEMORY(&stuff);"); 532 | break; 533 | 534 | case INSTRUCTION_ACTION_LSD_REGISTER: 535 | Emit("Action_LSD_REGISTER(&stuff);"); 536 | break; 537 | 538 | case INSTRUCTION_ACTION_ROD_MEMORY: 539 | Emit("Action_ROD_MEMORY(&stuff);"); 540 | break; 541 | 542 | case INSTRUCTION_ACTION_ROD_REGISTER: 543 | Emit("Action_ROD_REGISTER(&stuff);"); 544 | break; 545 | 546 | case INSTRUCTION_ACTION_ROXD_MEMORY: 547 | Emit("Action_ROXD_MEMORY(&stuff);"); 548 | break; 549 | 550 | case INSTRUCTION_ACTION_ROXD_REGISTER: 551 | Emit("Action_ROXD_REGISTER(&stuff);"); 552 | break; 553 | 554 | case INSTRUCTION_ACTION_UNIMPLEMENTED_1: 555 | Emit("Action_UNIMPLEMENTED_1(&stuff);"); 556 | break; 557 | 558 | case INSTRUCTION_ACTION_UNIMPLEMENTED_2: 559 | Emit("Action_UNIMPLEMENTED_2(&stuff);"); 560 | break; 561 | 562 | case INSTRUCTION_ACTION_NOP: 563 | Emit("Action_NOP(&stuff);"); 564 | break; 565 | } 566 | 567 | Emit(""); 568 | } 569 | 570 | void EmitInstructionWriteDestinationOperand(const Instruction instruction) 571 | { 572 | if (Instruction_IsDestinationOperandWritten(instruction)) 573 | { 574 | Emit("/* Write destination operand. */"); 575 | Emit("WriteDestination(&stuff);"); 576 | Emit(""); 577 | } 578 | } 579 | 580 | void EmitInstructionConditionCodes(const Instruction instruction) 581 | { 582 | Emit("/* Update the condition codes in the following order: */"); 583 | Emit("/* CARRY, OVERFLOW, ZERO, NEGATIVE, EXTEND */"); 584 | Emit(""); 585 | 586 | Emit("/* Update CARRY condition code */"); 587 | switch (Instruction_GetCarryModifier(instruction)) 588 | { 589 | case INSTRUCTION_CARRY_STANDARD_CARRY: 590 | Emit("Carry_StandardCarry(&stuff);"); 591 | break; 592 | 593 | case INSTRUCTION_CARRY_STANDARD_BORROW: 594 | Emit("Carry_StandardBorrow(&stuff);"); 595 | break; 596 | 597 | case INSTRUCTION_CARRY_NEG: 598 | Emit("Carry_NEG(&stuff);"); 599 | break; 600 | 601 | case INSTRUCTION_CARRY_CLEAR: 602 | Emit("Carry_Clear(&stuff);"); 603 | break; 604 | 605 | case INSTRUCTION_CARRY_UNDEFINED: 606 | Emit("/* Undefined */"); 607 | break; 608 | 609 | case INSTRUCTION_CARRY_UNAFFECTED: 610 | Emit("/* Unaffected */"); 611 | break; 612 | } 613 | 614 | Emit("/* Update OVERFLOW condition code */"); 615 | switch (Instruction_GetOverflowModifier(instruction)) 616 | { 617 | case INSTRUCTION_OVERFLOW_ADD: 618 | Emit("Overflow_ADD(&stuff);"); 619 | break; 620 | 621 | case INSTRUCTION_OVERFLOW_SUB: 622 | Emit("Overflow_SUB(&stuff);"); 623 | break; 624 | 625 | case INSTRUCTION_OVERFLOW_NEG: 626 | Emit("Overflow_NEG(&stuff);"); 627 | break; 628 | 629 | case INSTRUCTION_OVERFLOW_CLEARED: 630 | Emit("Overflow_Clear(&stuff);"); 631 | break; 632 | 633 | case INSTRUCTION_OVERFLOW_UNDEFINED: 634 | Emit("/* Undefined */"); 635 | break; 636 | 637 | case INSTRUCTION_OVERFLOW_UNAFFECTED: 638 | Emit("/* Unaffected */"); 639 | break; 640 | } 641 | 642 | Emit("/* Update ZERO condition code */"); 643 | switch (Instruction_GetZeroModifier(instruction)) 644 | { 645 | case INSTRUCTION_ZERO_CLEAR_IF_NONZERO_UNAFFECTED_OTHERWISE: 646 | Emit("Zero_ClearIfNonZeroUnaffectedOtherwise(&stuff);"); 647 | break; 648 | 649 | case INSTRUCTION_ZERO_SET_IF_ZERO_CLEAR_OTHERWISE: 650 | Emit("Zero_SetIfZeroClearOtherwise(&stuff);"); 651 | break; 652 | 653 | case INSTRUCTION_ZERO_UNDEFINED: 654 | Emit("/* Undefined */"); 655 | break; 656 | 657 | case INSTRUCTION_ZERO_UNAFFECTED: 658 | Emit("/* Unaffected */"); 659 | break; 660 | } 661 | 662 | Emit("/* Update NEGATIVE condition code */"); 663 | switch (Instruction_GetNegativeModifier(instruction)) 664 | { 665 | case INSTRUCTION_NEGATIVE_SET_IF_NEGATIVE_CLEAR_OTHERWISE: 666 | Emit("Negative_SetIfNegativeClearOtherwise(&stuff);"); 667 | break; 668 | 669 | case INSTRUCTION_NEGATIVE_UNAFFECTED: 670 | Emit("/* Unaffected */"); 671 | break; 672 | } 673 | 674 | Emit("/* Update EXTEND condition code */"); 675 | switch (Instruction_GetExtendModifier(instruction)) 676 | { 677 | case INSTRUCTION_EXTEND_SET_TO_CARRY: 678 | Emit("Extend_SetToCarry(&stuff);"); 679 | break; 680 | 681 | case INSTRUCTION_EXTEND_UNAFFECTED: 682 | Emit("/* Unaffected */"); 683 | break; 684 | } 685 | 686 | Emit(""); 687 | } 688 | -------------------------------------------------------------------------------- /interpreter/microcode-generator/emit-instructions.h: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INCLUDE_GUARD_0BB73C0B_EA27_45D8_AA97_E98FBFD79EFC 20 | #define INCLUDE_GUARD_0BB73C0B_EA27_45D8_AA97_E98FBFD79EFC 21 | 22 | #include "../../common/instruction.h" 23 | 24 | void EmitInstructionSupervisorCheck(const Instruction instruction); 25 | void EmitInstructionSize(const Instruction instruction); 26 | void EmitInstructionSourceAddressMode(const Instruction instruction); 27 | void EmitInstructionDestinationAddressMode(const Instruction instruction); 28 | void EmitInstructionReadSourceOperand(const Instruction instruction); 29 | void EmitInstructionReadDestinationOperand(const Instruction instruction); 30 | void EmitInstructionAction(const Instruction instruction); 31 | void EmitInstructionWriteDestinationOperand(const Instruction instruction); 32 | void EmitInstructionConditionCodes(const Instruction instruction); 33 | 34 | #endif /* INCLUDE_GUARD_0BB73C0B_EA27_45D8_AA97_E98FBFD79EFC */ 35 | -------------------------------------------------------------------------------- /interpreter/microcode-generator/emit.c: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "emit.h" 20 | 21 | #include 22 | #include 23 | 24 | #include "../../common/clowncommon/clowncommon.h" 25 | 26 | FILE *emit_file; 27 | unsigned int emit_indentation; 28 | 29 | void Emit(const char* const line) 30 | { 31 | if (line[0] != '\0') 32 | { 33 | unsigned int i; 34 | 35 | for (i = 0; i < emit_indentation; ++i) 36 | fputc('\t', emit_file); 37 | 38 | fputs(line, emit_file); 39 | } 40 | 41 | fputc('\n', emit_file); 42 | } 43 | 44 | void EmitFormatted(const char* const line, ...) 45 | { 46 | unsigned int i; 47 | va_list args; 48 | 49 | for (i = 0; i < emit_indentation; ++i) 50 | fputc('\t', emit_file); 51 | 52 | va_start(args, line); 53 | vfprintf(emit_file, line, args); 54 | va_end(args); 55 | 56 | fputc('\n', emit_file); 57 | } 58 | -------------------------------------------------------------------------------- /interpreter/microcode-generator/emit.h: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INCLUDE_GUARD_A3BEF769_9DE7_478E_BF00_AF24854A823C 20 | #define INCLUDE_GUARD_A3BEF769_9DE7_478E_BF00_AF24854A823C 21 | 22 | #include 23 | 24 | #include "../../common/clowncommon/clowncommon.h" 25 | 26 | extern FILE *emit_file; 27 | extern unsigned int emit_indentation; 28 | 29 | void Emit(const char* const line); 30 | CC_ATTRIBUTE_PRINTF(1, 2) void EmitFormatted(const char* const line, ...); 31 | 32 | #endif /* INCLUDE_GUARD_A3BEF769_9DE7_478E_BF00_AF24854A823C */ 33 | -------------------------------------------------------------------------------- /interpreter/microcode-generator/generator.c: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "emit.h" 23 | #include "emit-instructions.h" 24 | 25 | int main(int argc, char **argv) 26 | { 27 | static const char* const instruction_strings[] = { 28 | "INSTRUCTION_ABCD", 29 | "INSTRUCTION_ADD", 30 | "INSTRUCTION_ADDA", 31 | "INSTRUCTION_ADDAQ", 32 | "INSTRUCTION_ADDI", 33 | "INSTRUCTION_ADDQ", 34 | "INSTRUCTION_ADDX", 35 | "INSTRUCTION_AND", 36 | "INSTRUCTION_ANDI", 37 | "INSTRUCTION_ANDI_TO_CCR", 38 | "INSTRUCTION_ANDI_TO_SR", 39 | "INSTRUCTION_ASD_MEMORY", 40 | "INSTRUCTION_ASD_REGISTER", 41 | "INSTRUCTION_BCC_SHORT", 42 | "INSTRUCTION_BCC_WORD", 43 | "INSTRUCTION_BCHG_DYNAMIC", 44 | "INSTRUCTION_BCHG_STATIC", 45 | "INSTRUCTION_BCLR_DYNAMIC", 46 | "INSTRUCTION_BCLR_STATIC", 47 | "INSTRUCTION_BRA_SHORT", 48 | "INSTRUCTION_BRA_WORD", 49 | "INSTRUCTION_BSET_DYNAMIC", 50 | "INSTRUCTION_BSET_STATIC", 51 | "INSTRUCTION_BSR_SHORT", 52 | "INSTRUCTION_BSR_WORD", 53 | "INSTRUCTION_BTST_DYNAMIC", 54 | "INSTRUCTION_BTST_STATIC", 55 | "INSTRUCTION_CHK", 56 | "INSTRUCTION_CLR", 57 | "INSTRUCTION_CMP", 58 | "INSTRUCTION_CMPA", 59 | "INSTRUCTION_CMPI", 60 | "INSTRUCTION_CMPM", 61 | "INSTRUCTION_DBCC", 62 | "INSTRUCTION_DIVS", 63 | "INSTRUCTION_DIVU", 64 | "INSTRUCTION_EOR", 65 | "INSTRUCTION_EORI", 66 | "INSTRUCTION_EORI_TO_CCR", 67 | "INSTRUCTION_EORI_TO_SR", 68 | "INSTRUCTION_EXG", 69 | "INSTRUCTION_EXT", 70 | "INSTRUCTION_ILLEGAL", 71 | "INSTRUCTION_JMP", 72 | "INSTRUCTION_JSR", 73 | "INSTRUCTION_LEA", 74 | "INSTRUCTION_LINK", 75 | "INSTRUCTION_LSD_MEMORY", 76 | "INSTRUCTION_LSD_REGISTER", 77 | "INSTRUCTION_MOVE", 78 | "INSTRUCTION_MOVE_FROM_SR", 79 | "INSTRUCTION_MOVE_TO_CCR", 80 | "INSTRUCTION_MOVE_TO_SR", 81 | "INSTRUCTION_MOVE_USP", 82 | "INSTRUCTION_MOVEA", 83 | "INSTRUCTION_MOVEM", 84 | "INSTRUCTION_MOVEP", 85 | "INSTRUCTION_MOVEQ", 86 | "INSTRUCTION_MULS", 87 | "INSTRUCTION_MULU", 88 | "INSTRUCTION_NBCD", 89 | "INSTRUCTION_NEG", 90 | "INSTRUCTION_NEGX", 91 | "INSTRUCTION_NOP", 92 | "INSTRUCTION_NOT", 93 | "INSTRUCTION_OR", 94 | "INSTRUCTION_ORI", 95 | "INSTRUCTION_ORI_TO_CCR", 96 | "INSTRUCTION_ORI_TO_SR", 97 | "INSTRUCTION_PEA", 98 | "INSTRUCTION_RESET", 99 | "INSTRUCTION_ROD_MEMORY", 100 | "INSTRUCTION_ROD_REGISTER", 101 | "INSTRUCTION_ROXD_MEMORY", 102 | "INSTRUCTION_ROXD_REGISTER", 103 | "INSTRUCTION_RTE", 104 | "INSTRUCTION_RTR", 105 | "INSTRUCTION_RTS", 106 | "INSTRUCTION_SBCD", 107 | "INSTRUCTION_SCC", 108 | "INSTRUCTION_STOP", 109 | "INSTRUCTION_SUB", 110 | "INSTRUCTION_SUBA", 111 | "INSTRUCTION_SUBAQ", 112 | "INSTRUCTION_SUBI", 113 | "INSTRUCTION_SUBQ", 114 | "INSTRUCTION_SUBX", 115 | "INSTRUCTION_SWAP", 116 | "INSTRUCTION_TAS", 117 | "INSTRUCTION_TRAP", 118 | "INSTRUCTION_TRAPV", 119 | "INSTRUCTION_TST", 120 | "INSTRUCTION_UNLK", 121 | 122 | "INSTRUCTION_UNIMPLEMENTED_1", 123 | "INSTRUCTION_UNIMPLEMENTED_2" 124 | }; 125 | 126 | size_t i; 127 | 128 | (void)argc; 129 | (void)argv; 130 | 131 | emit_file = stdout; 132 | 133 | for (i = 0; i < CC_COUNT_OF(instruction_strings); ++i) 134 | { 135 | const Instruction instruction = (Instruction)i; 136 | 137 | EmitFormatted("case %s:", instruction_strings[i]); 138 | ++emit_indentation; 139 | EmitInstructionSupervisorCheck(instruction); 140 | EmitInstructionSize(instruction); 141 | EmitInstructionSourceAddressMode(instruction); 142 | EmitInstructionReadSourceOperand(instruction); 143 | EmitInstructionDestinationAddressMode(instruction); 144 | EmitInstructionReadDestinationOperand(instruction); 145 | EmitInstructionAction(instruction); 146 | EmitInstructionWriteDestinationOperand(instruction); 147 | EmitInstructionConditionCodes(instruction); 148 | Emit("break;"); 149 | --emit_indentation; 150 | Emit(""); 151 | } 152 | 153 | return EXIT_SUCCESS; 154 | } 155 | -------------------------------------------------------------------------------- /interpreter/microcode-generator/instruction-properties.c: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "instruction-properties.h" 20 | 21 | #include 22 | 23 | InstructionAction Instruction_GetAction(const Instruction instruction) 24 | { 25 | /* Do the actual instruction */ 26 | switch (instruction) 27 | { 28 | case INSTRUCTION_OR: 29 | case INSTRUCTION_ORI: 30 | case INSTRUCTION_ORI_TO_CCR: 31 | case INSTRUCTION_ORI_TO_SR: 32 | return INSTRUCTION_ACTION_OR; 33 | 34 | case INSTRUCTION_AND: 35 | case INSTRUCTION_ANDI: 36 | case INSTRUCTION_ANDI_TO_CCR: 37 | case INSTRUCTION_ANDI_TO_SR: 38 | return INSTRUCTION_ACTION_AND; 39 | 40 | case INSTRUCTION_CMPA: 41 | return INSTRUCTION_ACTION_CMPA; 42 | 43 | case INSTRUCTION_SUBA: 44 | return INSTRUCTION_ACTION_SUBA; 45 | 46 | case INSTRUCTION_SUBAQ: 47 | case INSTRUCTION_SUBQ: 48 | return INSTRUCTION_ACTION_SUBQ; 49 | 50 | case INSTRUCTION_CMP: 51 | return INSTRUCTION_ACTION_CMP; 52 | 53 | case INSTRUCTION_CMPI: 54 | return INSTRUCTION_ACTION_CMPI; 55 | 56 | case INSTRUCTION_CMPM: 57 | return INSTRUCTION_ACTION_CMPM; 58 | 59 | case INSTRUCTION_SUB: 60 | case INSTRUCTION_SUBI: 61 | return INSTRUCTION_ACTION_SUB; 62 | 63 | case INSTRUCTION_ADDA: 64 | return INSTRUCTION_ACTION_ADDA; 65 | 66 | case INSTRUCTION_ADDAQ: 67 | case INSTRUCTION_ADDQ: 68 | return INSTRUCTION_ACTION_ADDQ; 69 | 70 | case INSTRUCTION_ADD: 71 | case INSTRUCTION_ADDI: 72 | return INSTRUCTION_ACTION_ADD; 73 | 74 | case INSTRUCTION_EOR: 75 | case INSTRUCTION_EORI: 76 | case INSTRUCTION_EORI_TO_CCR: 77 | case INSTRUCTION_EORI_TO_SR: 78 | return INSTRUCTION_ACTION_EOR; 79 | 80 | case INSTRUCTION_TST: 81 | return INSTRUCTION_ACTION_TST; 82 | 83 | case INSTRUCTION_BCHG_DYNAMIC: 84 | case INSTRUCTION_BCHG_STATIC: 85 | return INSTRUCTION_ACTION_BCHG; 86 | 87 | case INSTRUCTION_BCLR_DYNAMIC: 88 | case INSTRUCTION_BCLR_STATIC: 89 | return INSTRUCTION_ACTION_BCLR; 90 | 91 | case INSTRUCTION_BSET_DYNAMIC: 92 | case INSTRUCTION_BSET_STATIC: 93 | return INSTRUCTION_ACTION_BSET; 94 | 95 | case INSTRUCTION_BTST_DYNAMIC: 96 | case INSTRUCTION_BTST_STATIC: 97 | return INSTRUCTION_ACTION_BTST; 98 | 99 | case INSTRUCTION_MOVEP: 100 | return INSTRUCTION_ACTION_MOVEP; 101 | 102 | case INSTRUCTION_MOVEA: 103 | return INSTRUCTION_ACTION_MOVEA; 104 | 105 | case INSTRUCTION_MOVE: 106 | case INSTRUCTION_MOVE_FROM_SR: 107 | case INSTRUCTION_MOVE_TO_CCR: 108 | case INSTRUCTION_MOVE_TO_SR: 109 | return INSTRUCTION_ACTION_MOVE; 110 | 111 | case INSTRUCTION_LINK: 112 | return INSTRUCTION_ACTION_LINK; 113 | 114 | case INSTRUCTION_UNLK: 115 | return INSTRUCTION_ACTION_UNLK; 116 | 117 | case INSTRUCTION_NEGX: 118 | return INSTRUCTION_ACTION_NEGX; 119 | 120 | case INSTRUCTION_CLR: 121 | return INSTRUCTION_ACTION_CLR; 122 | 123 | case INSTRUCTION_NEG: 124 | return INSTRUCTION_ACTION_NEG; 125 | 126 | case INSTRUCTION_NOT: 127 | return INSTRUCTION_ACTION_NOT; 128 | 129 | case INSTRUCTION_EXT: 130 | return INSTRUCTION_ACTION_EXT; 131 | 132 | case INSTRUCTION_NBCD: 133 | return INSTRUCTION_ACTION_NBCD; 134 | 135 | case INSTRUCTION_SWAP: 136 | return INSTRUCTION_ACTION_SWAP; 137 | 138 | case INSTRUCTION_PEA: 139 | return INSTRUCTION_ACTION_PEA; 140 | 141 | case INSTRUCTION_ILLEGAL: 142 | return INSTRUCTION_ACTION_ILLEGAL; 143 | 144 | case INSTRUCTION_TAS: 145 | return INSTRUCTION_ACTION_TAS; 146 | 147 | case INSTRUCTION_TRAP: 148 | return INSTRUCTION_ACTION_TRAP; 149 | 150 | case INSTRUCTION_MOVE_USP: 151 | return INSTRUCTION_ACTION_MOVE_USP; 152 | 153 | case INSTRUCTION_RESET: 154 | return INSTRUCTION_ACTION_RESET; 155 | 156 | case INSTRUCTION_STOP: 157 | return INSTRUCTION_ACTION_STOP; 158 | 159 | case INSTRUCTION_RTE: 160 | return INSTRUCTION_ACTION_RTE; 161 | 162 | case INSTRUCTION_RTS: 163 | return INSTRUCTION_ACTION_RTS; 164 | 165 | case INSTRUCTION_TRAPV: 166 | return INSTRUCTION_ACTION_TRAPV; 167 | 168 | case INSTRUCTION_RTR: 169 | return INSTRUCTION_ACTION_RTR; 170 | 171 | case INSTRUCTION_JSR: 172 | return INSTRUCTION_ACTION_JSR; 173 | 174 | case INSTRUCTION_JMP: 175 | return INSTRUCTION_ACTION_JMP; 176 | 177 | case INSTRUCTION_LEA: 178 | return INSTRUCTION_ACTION_LEA; 179 | 180 | case INSTRUCTION_MOVEM: 181 | return INSTRUCTION_ACTION_MOVEM; 182 | 183 | case INSTRUCTION_CHK: 184 | return INSTRUCTION_ACTION_CHK; 185 | 186 | case INSTRUCTION_SCC: 187 | return INSTRUCTION_ACTION_SCC; 188 | 189 | case INSTRUCTION_DBCC: 190 | return INSTRUCTION_ACTION_DBCC; 191 | 192 | case INSTRUCTION_BRA_SHORT: 193 | return INSTRUCTION_ACTION_BRA_SHORT; 194 | 195 | case INSTRUCTION_BRA_WORD: 196 | return INSTRUCTION_ACTION_BRA_WORD; 197 | 198 | case INSTRUCTION_BSR_SHORT: 199 | return INSTRUCTION_ACTION_BSR_SHORT; 200 | 201 | case INSTRUCTION_BSR_WORD: 202 | return INSTRUCTION_ACTION_BSR_WORD; 203 | 204 | case INSTRUCTION_BCC_SHORT: 205 | return INSTRUCTION_ACTION_BCC_SHORT; 206 | 207 | case INSTRUCTION_BCC_WORD: 208 | return INSTRUCTION_ACTION_BCC_WORD; 209 | 210 | case INSTRUCTION_MOVEQ: 211 | return INSTRUCTION_ACTION_MOVEQ; 212 | 213 | case INSTRUCTION_DIVS: 214 | return INSTRUCTION_ACTION_DIVS; 215 | 216 | case INSTRUCTION_DIVU: 217 | return INSTRUCTION_ACTION_DIVU; 218 | 219 | case INSTRUCTION_SBCD: 220 | return INSTRUCTION_ACTION_SBCD; 221 | 222 | case INSTRUCTION_SUBX: 223 | return INSTRUCTION_ACTION_SUBX; 224 | 225 | case INSTRUCTION_MULS: 226 | return INSTRUCTION_ACTION_MULS; 227 | 228 | case INSTRUCTION_MULU: 229 | return INSTRUCTION_ACTION_MULU; 230 | 231 | case INSTRUCTION_ABCD: 232 | return INSTRUCTION_ACTION_ABCD; 233 | 234 | case INSTRUCTION_EXG: 235 | return INSTRUCTION_ACTION_EXG; 236 | 237 | case INSTRUCTION_ADDX: 238 | return INSTRUCTION_ACTION_ADDX; 239 | 240 | case INSTRUCTION_ASD_MEMORY: 241 | return INSTRUCTION_ACTION_ASD_MEMORY; 242 | 243 | case INSTRUCTION_ASD_REGISTER: 244 | return INSTRUCTION_ACTION_ASD_REGISTER; 245 | 246 | case INSTRUCTION_LSD_MEMORY: 247 | return INSTRUCTION_ACTION_LSD_MEMORY; 248 | 249 | case INSTRUCTION_LSD_REGISTER: 250 | return INSTRUCTION_ACTION_LSD_REGISTER; 251 | 252 | case INSTRUCTION_ROD_MEMORY: 253 | return INSTRUCTION_ACTION_ROD_MEMORY; 254 | 255 | case INSTRUCTION_ROD_REGISTER: 256 | return INSTRUCTION_ACTION_ROD_REGISTER; 257 | 258 | case INSTRUCTION_ROXD_MEMORY: 259 | return INSTRUCTION_ACTION_ROXD_MEMORY; 260 | 261 | case INSTRUCTION_ROXD_REGISTER: 262 | return INSTRUCTION_ACTION_ROXD_REGISTER; 263 | 264 | case INSTRUCTION_UNIMPLEMENTED_1: 265 | return INSTRUCTION_ACTION_UNIMPLEMENTED_1; 266 | 267 | case INSTRUCTION_UNIMPLEMENTED_2: 268 | return INSTRUCTION_ACTION_UNIMPLEMENTED_2; 269 | 270 | case INSTRUCTION_NOP: 271 | return INSTRUCTION_ACTION_NOP; 272 | } 273 | 274 | assert(cc_false); 275 | 276 | return INSTRUCTION_ACTION_NOP; 277 | } 278 | 279 | cc_bool Instruction_IsSourceOperandRead(const Instruction instruction) 280 | { 281 | /* Obtain source value. */ 282 | switch (instruction) 283 | { 284 | case INSTRUCTION_ORI_TO_CCR: 285 | case INSTRUCTION_ORI_TO_SR: 286 | case INSTRUCTION_ORI: 287 | case INSTRUCTION_ANDI_TO_CCR: 288 | case INSTRUCTION_ANDI_TO_SR: 289 | case INSTRUCTION_ANDI: 290 | case INSTRUCTION_SUBI: 291 | case INSTRUCTION_ADDI: 292 | case INSTRUCTION_EORI_TO_CCR: 293 | case INSTRUCTION_EORI_TO_SR: 294 | case INSTRUCTION_EORI: 295 | case INSTRUCTION_CMPI: 296 | case INSTRUCTION_LINK: 297 | case INSTRUCTION_MOVEM: 298 | case INSTRUCTION_DBCC: 299 | case INSTRUCTION_STOP: 300 | case INSTRUCTION_BTST_DYNAMIC: 301 | case INSTRUCTION_BCHG_DYNAMIC: 302 | case INSTRUCTION_BCLR_DYNAMIC: 303 | case INSTRUCTION_BSET_DYNAMIC: 304 | case INSTRUCTION_EOR: 305 | case INSTRUCTION_BTST_STATIC: 306 | case INSTRUCTION_BCHG_STATIC: 307 | case INSTRUCTION_BCLR_STATIC: 308 | case INSTRUCTION_BSET_STATIC: 309 | case INSTRUCTION_SBCD: 310 | case INSTRUCTION_ABCD: 311 | case INSTRUCTION_SUBX: 312 | case INSTRUCTION_ADDX: 313 | case INSTRUCTION_OR: 314 | case INSTRUCTION_SUB: 315 | case INSTRUCTION_AND: 316 | case INSTRUCTION_ADD: 317 | case INSTRUCTION_CMPM: 318 | case INSTRUCTION_MOVEA: 319 | case INSTRUCTION_MOVE: 320 | case INSTRUCTION_MOVE_FROM_SR: 321 | case INSTRUCTION_MOVE_TO_CCR: 322 | case INSTRUCTION_MOVE_TO_SR: 323 | case INSTRUCTION_CHK: 324 | case INSTRUCTION_DIVU: 325 | case INSTRUCTION_DIVS: 326 | case INSTRUCTION_SUBA: 327 | case INSTRUCTION_CMP: 328 | case INSTRUCTION_CMPA: 329 | case INSTRUCTION_MULU: 330 | case INSTRUCTION_MULS: 331 | case INSTRUCTION_ADDA: 332 | case INSTRUCTION_TST: 333 | case INSTRUCTION_BRA_WORD: 334 | case INSTRUCTION_BSR_WORD: 335 | case INSTRUCTION_BCC_WORD: 336 | case INSTRUCTION_PEA: 337 | case INSTRUCTION_JSR: 338 | case INSTRUCTION_JMP: 339 | case INSTRUCTION_LEA: 340 | return cc_true; 341 | 342 | case INSTRUCTION_ADDAQ: 343 | case INSTRUCTION_SUBAQ: 344 | case INSTRUCTION_ADDQ: 345 | case INSTRUCTION_SUBQ: 346 | case INSTRUCTION_TRAP: 347 | case INSTRUCTION_BRA_SHORT: 348 | case INSTRUCTION_BSR_SHORT: 349 | case INSTRUCTION_BCC_SHORT: 350 | case INSTRUCTION_MOVEP: 351 | case INSTRUCTION_NEGX: 352 | case INSTRUCTION_CLR: 353 | case INSTRUCTION_NEG: 354 | case INSTRUCTION_NOT: 355 | case INSTRUCTION_EXT: 356 | case INSTRUCTION_NBCD: 357 | case INSTRUCTION_SWAP: 358 | case INSTRUCTION_ILLEGAL: 359 | case INSTRUCTION_TAS: 360 | case INSTRUCTION_UNLK: 361 | case INSTRUCTION_MOVE_USP: 362 | case INSTRUCTION_RESET: 363 | case INSTRUCTION_NOP: 364 | case INSTRUCTION_RTE: 365 | case INSTRUCTION_RTS: 366 | case INSTRUCTION_TRAPV: 367 | case INSTRUCTION_RTR: 368 | case INSTRUCTION_SCC: 369 | case INSTRUCTION_MOVEQ: 370 | case INSTRUCTION_EXG: 371 | case INSTRUCTION_ASD_MEMORY: 372 | case INSTRUCTION_LSD_MEMORY: 373 | case INSTRUCTION_ROXD_MEMORY: 374 | case INSTRUCTION_ROD_MEMORY: 375 | case INSTRUCTION_ASD_REGISTER: 376 | case INSTRUCTION_LSD_REGISTER: 377 | case INSTRUCTION_ROXD_REGISTER: 378 | case INSTRUCTION_ROD_REGISTER: 379 | case INSTRUCTION_UNIMPLEMENTED_1: 380 | case INSTRUCTION_UNIMPLEMENTED_2: 381 | return cc_false; 382 | } 383 | 384 | assert(cc_false); 385 | 386 | return cc_false; 387 | } 388 | 389 | cc_bool Instruction_IsDestinationOperandRead(const Instruction instruction) 390 | { 391 | /* Obtain destination value */ 392 | switch (instruction) 393 | { 394 | case INSTRUCTION_CLR: 395 | case INSTRUCTION_SCC: 396 | /* For some reason, the above two instructions read from their destination even though they don't use it. */ 397 | case INSTRUCTION_ORI_TO_CCR: 398 | case INSTRUCTION_ORI_TO_SR: 399 | case INSTRUCTION_ANDI_TO_CCR: 400 | case INSTRUCTION_ANDI_TO_SR: 401 | case INSTRUCTION_EORI_TO_CCR: 402 | case INSTRUCTION_EORI_TO_SR: 403 | case INSTRUCTION_ORI: 404 | case INSTRUCTION_ANDI: 405 | case INSTRUCTION_SUBI: 406 | case INSTRUCTION_ADDI: 407 | case INSTRUCTION_EORI: 408 | case INSTRUCTION_CMPI: 409 | case INSTRUCTION_BTST_STATIC: 410 | case INSTRUCTION_BCHG_STATIC: 411 | case INSTRUCTION_BCLR_STATIC: 412 | case INSTRUCTION_BSET_STATIC: 413 | case INSTRUCTION_BTST_DYNAMIC: 414 | case INSTRUCTION_BCHG_DYNAMIC: 415 | case INSTRUCTION_BCLR_DYNAMIC: 416 | case INSTRUCTION_BSET_DYNAMIC: 417 | case INSTRUCTION_NEGX: 418 | case INSTRUCTION_NEG: 419 | case INSTRUCTION_NOT: 420 | case INSTRUCTION_NBCD: 421 | case INSTRUCTION_TAS: 422 | case INSTRUCTION_EXT: 423 | case INSTRUCTION_SWAP: 424 | case INSTRUCTION_ADDAQ: 425 | case INSTRUCTION_SUBAQ: 426 | case INSTRUCTION_ADDQ: 427 | case INSTRUCTION_SUBQ: 428 | case INSTRUCTION_SBCD: 429 | case INSTRUCTION_OR: 430 | case INSTRUCTION_SUB: 431 | case INSTRUCTION_SUBX: 432 | case INSTRUCTION_EOR: 433 | case INSTRUCTION_SUBA: 434 | case INSTRUCTION_CMPM: 435 | case INSTRUCTION_CMP: 436 | case INSTRUCTION_CMPA: 437 | case INSTRUCTION_ABCD: 438 | case INSTRUCTION_AND: 439 | case INSTRUCTION_ADD: 440 | case INSTRUCTION_ADDX: 441 | case INSTRUCTION_ADDA: 442 | case INSTRUCTION_MOVEM: 443 | case INSTRUCTION_MOVEP: 444 | case INSTRUCTION_DIVS: 445 | case INSTRUCTION_DIVU: 446 | case INSTRUCTION_MULS: 447 | case INSTRUCTION_MULU: 448 | case INSTRUCTION_ASD_MEMORY: 449 | case INSTRUCTION_LSD_MEMORY: 450 | case INSTRUCTION_ROXD_MEMORY: 451 | case INSTRUCTION_ROD_MEMORY: 452 | case INSTRUCTION_ASD_REGISTER: 453 | case INSTRUCTION_LSD_REGISTER: 454 | case INSTRUCTION_ROXD_REGISTER: 455 | case INSTRUCTION_ROD_REGISTER: 456 | return cc_true; 457 | 458 | case INSTRUCTION_BRA_SHORT: 459 | case INSTRUCTION_BRA_WORD: 460 | case INSTRUCTION_BSR_SHORT: 461 | case INSTRUCTION_BSR_WORD: 462 | case INSTRUCTION_BCC_SHORT: 463 | case INSTRUCTION_BCC_WORD: 464 | case INSTRUCTION_CHK: 465 | case INSTRUCTION_DBCC: 466 | case INSTRUCTION_EXG: 467 | case INSTRUCTION_ILLEGAL: 468 | case INSTRUCTION_JMP: 469 | case INSTRUCTION_JSR: 470 | case INSTRUCTION_LEA: 471 | case INSTRUCTION_LINK: 472 | case INSTRUCTION_MOVE: 473 | case INSTRUCTION_MOVE_FROM_SR: 474 | case INSTRUCTION_MOVE_TO_CCR: 475 | case INSTRUCTION_MOVE_TO_SR: 476 | case INSTRUCTION_MOVE_USP: 477 | case INSTRUCTION_MOVEA: 478 | case INSTRUCTION_MOVEQ: 479 | case INSTRUCTION_NOP: 480 | case INSTRUCTION_PEA: 481 | case INSTRUCTION_RESET: 482 | case INSTRUCTION_RTE: 483 | case INSTRUCTION_RTR: 484 | case INSTRUCTION_RTS: 485 | case INSTRUCTION_STOP: 486 | case INSTRUCTION_TRAP: 487 | case INSTRUCTION_TRAPV: 488 | case INSTRUCTION_TST: 489 | case INSTRUCTION_UNLK: 490 | case INSTRUCTION_UNIMPLEMENTED_1: 491 | case INSTRUCTION_UNIMPLEMENTED_2: 492 | return cc_false; 493 | } 494 | 495 | assert(cc_false); 496 | 497 | return cc_false; 498 | } 499 | 500 | cc_bool Instruction_IsDestinationOperandWritten(const Instruction instruction) 501 | { 502 | /* Write output to destination */ 503 | switch (instruction) 504 | { 505 | case INSTRUCTION_ANDI_TO_CCR: 506 | case INSTRUCTION_EORI_TO_CCR: 507 | case INSTRUCTION_MOVE_TO_CCR: 508 | case INSTRUCTION_ORI_TO_CCR: 509 | case INSTRUCTION_ANDI_TO_SR: 510 | case INSTRUCTION_EORI_TO_SR: 511 | case INSTRUCTION_MOVE_TO_SR: 512 | case INSTRUCTION_ORI_TO_SR: 513 | case INSTRUCTION_ABCD: 514 | case INSTRUCTION_ADD: 515 | case INSTRUCTION_ADDA: 516 | case INSTRUCTION_ADDAQ: 517 | case INSTRUCTION_ADDI: 518 | case INSTRUCTION_ADDQ: 519 | case INSTRUCTION_ADDX: 520 | case INSTRUCTION_AND: 521 | case INSTRUCTION_ANDI: 522 | case INSTRUCTION_ASD_MEMORY: 523 | case INSTRUCTION_ASD_REGISTER: 524 | case INSTRUCTION_BCHG_DYNAMIC: 525 | case INSTRUCTION_BCHG_STATIC: 526 | case INSTRUCTION_BCLR_DYNAMIC: 527 | case INSTRUCTION_BCLR_STATIC: 528 | case INSTRUCTION_BSET_DYNAMIC: 529 | case INSTRUCTION_BSET_STATIC: 530 | case INSTRUCTION_CLR: 531 | case INSTRUCTION_DIVS: 532 | case INSTRUCTION_DIVU: 533 | case INSTRUCTION_EOR: 534 | case INSTRUCTION_EORI: 535 | case INSTRUCTION_EXT: 536 | case INSTRUCTION_OR: 537 | case INSTRUCTION_ORI: 538 | case INSTRUCTION_LEA: 539 | case INSTRUCTION_LSD_MEMORY: 540 | case INSTRUCTION_LSD_REGISTER: 541 | case INSTRUCTION_MOVE: 542 | case INSTRUCTION_MOVE_FROM_SR: 543 | case INSTRUCTION_MOVEA: 544 | case INSTRUCTION_MOVEQ: 545 | case INSTRUCTION_MULS: 546 | case INSTRUCTION_MULU: 547 | case INSTRUCTION_NBCD: 548 | case INSTRUCTION_NEG: 549 | case INSTRUCTION_NEGX: 550 | case INSTRUCTION_NOT: 551 | case INSTRUCTION_ROD_MEMORY: 552 | case INSTRUCTION_ROD_REGISTER: 553 | case INSTRUCTION_ROXD_MEMORY: 554 | case INSTRUCTION_ROXD_REGISTER: 555 | case INSTRUCTION_SBCD: 556 | case INSTRUCTION_SCC: 557 | case INSTRUCTION_SUB: 558 | case INSTRUCTION_SUBA: 559 | case INSTRUCTION_SUBAQ: 560 | case INSTRUCTION_SUBI: 561 | case INSTRUCTION_SUBQ: 562 | case INSTRUCTION_SUBX: 563 | case INSTRUCTION_SWAP: 564 | case INSTRUCTION_TAS: 565 | return cc_true; 566 | 567 | case INSTRUCTION_BRA_SHORT: 568 | case INSTRUCTION_BRA_WORD: 569 | case INSTRUCTION_BSR_SHORT: 570 | case INSTRUCTION_BSR_WORD: 571 | case INSTRUCTION_BCC_SHORT: 572 | case INSTRUCTION_BCC_WORD: 573 | case INSTRUCTION_BTST_STATIC: 574 | case INSTRUCTION_BTST_DYNAMIC: 575 | case INSTRUCTION_CHK: 576 | case INSTRUCTION_CMP: 577 | case INSTRUCTION_CMPA: 578 | case INSTRUCTION_CMPI: 579 | case INSTRUCTION_CMPM: 580 | case INSTRUCTION_DBCC: 581 | case INSTRUCTION_EXG: 582 | case INSTRUCTION_ILLEGAL: 583 | case INSTRUCTION_JMP: 584 | case INSTRUCTION_JSR: 585 | case INSTRUCTION_LINK: 586 | case INSTRUCTION_MOVE_USP: 587 | case INSTRUCTION_MOVEM: 588 | case INSTRUCTION_MOVEP: 589 | case INSTRUCTION_NOP: 590 | case INSTRUCTION_PEA: 591 | case INSTRUCTION_RESET: 592 | case INSTRUCTION_RTE: 593 | case INSTRUCTION_RTR: 594 | case INSTRUCTION_RTS: 595 | case INSTRUCTION_STOP: 596 | case INSTRUCTION_TRAP: 597 | case INSTRUCTION_TRAPV: 598 | case INSTRUCTION_TST: 599 | case INSTRUCTION_UNLK: 600 | case INSTRUCTION_UNIMPLEMENTED_1: 601 | case INSTRUCTION_UNIMPLEMENTED_2: 602 | return cc_false; 603 | } 604 | 605 | assert(cc_false); 606 | 607 | return cc_false; 608 | } 609 | 610 | InstructionSize Instruction_GetSize(const Instruction instruction) 611 | { 612 | switch (instruction) 613 | { 614 | case INSTRUCTION_ORI_TO_CCR: 615 | case INSTRUCTION_ANDI_TO_CCR: 616 | case INSTRUCTION_EORI_TO_CCR: 617 | case INSTRUCTION_NBCD: 618 | case INSTRUCTION_TAS: 619 | case INSTRUCTION_SCC: 620 | case INSTRUCTION_SBCD: 621 | case INSTRUCTION_ABCD: 622 | /* Hardcoded to a byte. */ 623 | return INSTRUCTION_SIZE_BYTE; 624 | 625 | case INSTRUCTION_ORI_TO_SR: 626 | case INSTRUCTION_ANDI_TO_SR: 627 | case INSTRUCTION_EORI_TO_SR: 628 | case INSTRUCTION_MOVE_FROM_SR: 629 | case INSTRUCTION_MOVE_TO_SR: 630 | case INSTRUCTION_MOVE_TO_CCR: 631 | case INSTRUCTION_LINK: 632 | case INSTRUCTION_MOVEM: 633 | case INSTRUCTION_CHK: 634 | case INSTRUCTION_DBCC: 635 | case INSTRUCTION_ASD_MEMORY: 636 | case INSTRUCTION_LSD_MEMORY: 637 | case INSTRUCTION_ROXD_MEMORY: 638 | case INSTRUCTION_ROD_MEMORY: 639 | case INSTRUCTION_STOP: 640 | /* Hardcoded to a word. */ 641 | return INSTRUCTION_SIZE_WORD; 642 | 643 | case INSTRUCTION_ADDAQ: 644 | case INSTRUCTION_SUBAQ: 645 | case INSTRUCTION_SWAP: 646 | case INSTRUCTION_LEA: 647 | case INSTRUCTION_MOVEQ: 648 | case INSTRUCTION_DIVU: 649 | case INSTRUCTION_DIVS: 650 | case INSTRUCTION_MULU: 651 | case INSTRUCTION_MULS: 652 | case INSTRUCTION_SUBA: 653 | case INSTRUCTION_CMPA: 654 | case INSTRUCTION_ADDA: 655 | /* Hardcoded to a longword. */ 656 | return INSTRUCTION_SIZE_LONGWORD; 657 | 658 | case INSTRUCTION_BTST_STATIC: 659 | case INSTRUCTION_BCHG_STATIC: 660 | case INSTRUCTION_BCLR_STATIC: 661 | case INSTRUCTION_BSET_STATIC: 662 | case INSTRUCTION_BTST_DYNAMIC: 663 | case INSTRUCTION_BCHG_DYNAMIC: 664 | case INSTRUCTION_BCLR_DYNAMIC: 665 | case INSTRUCTION_BSET_DYNAMIC: 666 | /* 4 if register - 1 if memory. */ 667 | return INSTRUCTION_SIZE_LONGWORD_REGISTER_BYTE_MEMORY; 668 | 669 | case INSTRUCTION_MOVEA: 670 | case INSTRUCTION_MOVE: 671 | /* Derived from an odd bitfield. */ 672 | return INSTRUCTION_SIZE_MOVE; 673 | 674 | case INSTRUCTION_EXT: 675 | return INSTRUCTION_SIZE_EXT; 676 | 677 | case INSTRUCTION_ORI: 678 | case INSTRUCTION_ANDI: 679 | case INSTRUCTION_SUBI: 680 | case INSTRUCTION_ADDI: 681 | case INSTRUCTION_EORI: 682 | case INSTRUCTION_CMPI: 683 | case INSTRUCTION_NEGX: 684 | case INSTRUCTION_CLR: 685 | case INSTRUCTION_NEG: 686 | case INSTRUCTION_NOT: 687 | case INSTRUCTION_TST: 688 | case INSTRUCTION_OR: 689 | case INSTRUCTION_SUB: 690 | case INSTRUCTION_SUBX: 691 | case INSTRUCTION_EOR: 692 | case INSTRUCTION_CMPM: 693 | case INSTRUCTION_CMP: 694 | case INSTRUCTION_AND: 695 | case INSTRUCTION_ADD: 696 | case INSTRUCTION_ADDQ: 697 | case INSTRUCTION_SUBQ: 698 | case INSTRUCTION_ADDX: 699 | case INSTRUCTION_ASD_REGISTER: 700 | case INSTRUCTION_LSD_REGISTER: 701 | case INSTRUCTION_ROXD_REGISTER: 702 | case INSTRUCTION_ROD_REGISTER: 703 | /* Standard. */ 704 | return INSTRUCTION_SIZE_STANDARD; 705 | 706 | case INSTRUCTION_MOVEP: 707 | case INSTRUCTION_PEA: 708 | case INSTRUCTION_ILLEGAL: 709 | case INSTRUCTION_TRAP: 710 | case INSTRUCTION_UNLK: 711 | case INSTRUCTION_MOVE_USP: 712 | case INSTRUCTION_RESET: 713 | case INSTRUCTION_NOP: 714 | case INSTRUCTION_RTE: 715 | case INSTRUCTION_RTS: 716 | case INSTRUCTION_TRAPV: 717 | case INSTRUCTION_RTR: 718 | case INSTRUCTION_JSR: 719 | case INSTRUCTION_JMP: 720 | case INSTRUCTION_BRA_SHORT: 721 | case INSTRUCTION_BRA_WORD: 722 | case INSTRUCTION_BSR_SHORT: 723 | case INSTRUCTION_BSR_WORD: 724 | case INSTRUCTION_BCC_SHORT: 725 | case INSTRUCTION_BCC_WORD: 726 | case INSTRUCTION_EXG: 727 | case INSTRUCTION_UNIMPLEMENTED_1: 728 | case INSTRUCTION_UNIMPLEMENTED_2: 729 | /* Doesn't have a size. */ 730 | return INSTRUCTION_SIZE_NONE; 731 | } 732 | 733 | assert(cc_false); 734 | 735 | return INSTRUCTION_SIZE_NONE; 736 | } 737 | 738 | InstructionSourceOperand Instruction_GetSourceOperand(const Instruction instruction) 739 | { 740 | switch (instruction) 741 | { 742 | case INSTRUCTION_ORI_TO_CCR: 743 | case INSTRUCTION_ORI_TO_SR: 744 | case INSTRUCTION_ORI: 745 | case INSTRUCTION_ANDI_TO_CCR: 746 | case INSTRUCTION_ANDI_TO_SR: 747 | case INSTRUCTION_ANDI: 748 | case INSTRUCTION_SUBI: 749 | case INSTRUCTION_ADDI: 750 | case INSTRUCTION_EORI_TO_CCR: 751 | case INSTRUCTION_EORI_TO_SR: 752 | case INSTRUCTION_EORI: 753 | case INSTRUCTION_CMPI: 754 | case INSTRUCTION_LINK: 755 | case INSTRUCTION_MOVEM: 756 | case INSTRUCTION_DBCC: 757 | case INSTRUCTION_STOP: 758 | return INSTRUCTION_SOURCE_IMMEDIATE_DATA; 759 | 760 | case INSTRUCTION_BTST_DYNAMIC: 761 | case INSTRUCTION_BCHG_DYNAMIC: 762 | case INSTRUCTION_BCLR_DYNAMIC: 763 | case INSTRUCTION_BSET_DYNAMIC: 764 | case INSTRUCTION_EOR: 765 | return INSTRUCTION_SOURCE_DATA_REGISTER_SECONDARY; 766 | 767 | case INSTRUCTION_BTST_STATIC: 768 | case INSTRUCTION_BCHG_STATIC: 769 | case INSTRUCTION_BCLR_STATIC: 770 | case INSTRUCTION_BSET_STATIC: 771 | return INSTRUCTION_SOURCE_IMMEDIATE_DATA_BYTE; 772 | 773 | case INSTRUCTION_PEA: 774 | case INSTRUCTION_JSR: 775 | case INSTRUCTION_JMP: 776 | case INSTRUCTION_LEA: 777 | return INSTRUCTION_SOURCE_MEMORY_ADDRESS_PRIMARY; 778 | 779 | case INSTRUCTION_MOVE_FROM_SR: 780 | return INSTRUCTION_SOURCE_STATUS_REGISTER; 781 | 782 | case INSTRUCTION_ADDAQ: 783 | case INSTRUCTION_SUBAQ: 784 | case INSTRUCTION_ADDQ: 785 | case INSTRUCTION_SUBQ: 786 | case INSTRUCTION_TRAP: 787 | /* Doesn't need an address mode for its source. */ 788 | return INSTRUCTION_SOURCE_NONE; 789 | 790 | case INSTRUCTION_BRA_WORD: 791 | case INSTRUCTION_BSR_WORD: 792 | case INSTRUCTION_BCC_WORD: 793 | return INSTRUCTION_SOURCE_IMMEDIATE_DATA_WORD; 794 | 795 | case INSTRUCTION_SBCD: 796 | case INSTRUCTION_ABCD: 797 | case INSTRUCTION_SUBX: 798 | case INSTRUCTION_ADDX: 799 | return INSTRUCTION_SOURCE_BCD_X; 800 | 801 | case INSTRUCTION_OR: 802 | case INSTRUCTION_SUB: 803 | case INSTRUCTION_AND: 804 | case INSTRUCTION_ADD: 805 | return INSTRUCTION_SOURCE_DATA_REGISTER_SECONDARY_OR_PRIMARY_ADDRESS_MODE; 806 | 807 | case INSTRUCTION_SUBA: 808 | case INSTRUCTION_CMPA: 809 | case INSTRUCTION_ADDA: 810 | return INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE_SIZED; 811 | 812 | case INSTRUCTION_CMPM: 813 | return INSTRUCTION_SOURCE_ADDRESS_REGISTER_PRIMARY_POSTINCREMENT; 814 | 815 | case INSTRUCTION_MOVEA: 816 | case INSTRUCTION_MOVE: 817 | case INSTRUCTION_MOVE_TO_CCR: 818 | case INSTRUCTION_MOVE_TO_SR: 819 | case INSTRUCTION_CHK: 820 | case INSTRUCTION_CMP: 821 | case INSTRUCTION_TST: 822 | return INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE; 823 | 824 | case INSTRUCTION_DIVU: 825 | case INSTRUCTION_DIVS: 826 | case INSTRUCTION_MULU: 827 | case INSTRUCTION_MULS: 828 | return INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE_WORD; 829 | 830 | case INSTRUCTION_BRA_SHORT: 831 | case INSTRUCTION_BSR_SHORT: 832 | case INSTRUCTION_BCC_SHORT: 833 | case INSTRUCTION_MOVEP: 834 | case INSTRUCTION_NEGX: 835 | case INSTRUCTION_CLR: 836 | case INSTRUCTION_NEG: 837 | case INSTRUCTION_NOT: 838 | case INSTRUCTION_EXT: 839 | case INSTRUCTION_NBCD: 840 | case INSTRUCTION_SWAP: 841 | case INSTRUCTION_ILLEGAL: 842 | case INSTRUCTION_TAS: 843 | case INSTRUCTION_UNLK: 844 | case INSTRUCTION_MOVE_USP: 845 | case INSTRUCTION_RESET: 846 | case INSTRUCTION_NOP: 847 | case INSTRUCTION_RTE: 848 | case INSTRUCTION_RTS: 849 | case INSTRUCTION_TRAPV: 850 | case INSTRUCTION_RTR: 851 | case INSTRUCTION_SCC: 852 | case INSTRUCTION_MOVEQ: 853 | case INSTRUCTION_EXG: 854 | case INSTRUCTION_ASD_MEMORY: 855 | case INSTRUCTION_LSD_MEMORY: 856 | case INSTRUCTION_ROXD_MEMORY: 857 | case INSTRUCTION_ROD_MEMORY: 858 | case INSTRUCTION_ASD_REGISTER: 859 | case INSTRUCTION_LSD_REGISTER: 860 | case INSTRUCTION_ROXD_REGISTER: 861 | case INSTRUCTION_ROD_REGISTER: 862 | case INSTRUCTION_UNIMPLEMENTED_1: 863 | case INSTRUCTION_UNIMPLEMENTED_2: 864 | return INSTRUCTION_SOURCE_NONE; 865 | } 866 | 867 | assert(cc_false); 868 | 869 | return INSTRUCTION_SOURCE_NONE; 870 | } 871 | 872 | InstructionDestinationOperand Instruction_GetDestinationOperand(const Instruction instruction) 873 | { 874 | /* Decode destination address mode */ 875 | switch (instruction) 876 | { 877 | case INSTRUCTION_EXT: 878 | case INSTRUCTION_SWAP: 879 | case INSTRUCTION_ASD_REGISTER: 880 | case INSTRUCTION_LSD_REGISTER: 881 | case INSTRUCTION_ROXD_REGISTER: 882 | case INSTRUCTION_ROD_REGISTER: 883 | return INSTRUCTION_DESTINATION_DATA_REGISTER_PRIMARY; 884 | 885 | case INSTRUCTION_MOVEQ: 886 | case INSTRUCTION_CMP: 887 | case INSTRUCTION_DIVU: 888 | case INSTRUCTION_DIVS: 889 | case INSTRUCTION_MULU: 890 | case INSTRUCTION_MULS: 891 | return INSTRUCTION_DESTINATION_DATA_REGISTER_SECONDARY; 892 | 893 | case INSTRUCTION_LEA: 894 | case INSTRUCTION_SUBA: 895 | case INSTRUCTION_CMPA: 896 | case INSTRUCTION_ADDA: 897 | return INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY; 898 | 899 | case INSTRUCTION_MOVE: 900 | return INSTRUCTION_DESTINATION_SECONDARY_ADDRESS_MODE; 901 | 902 | case INSTRUCTION_SBCD: 903 | case INSTRUCTION_SUBX: 904 | case INSTRUCTION_ABCD: 905 | case INSTRUCTION_ADDX: 906 | return INSTRUCTION_DESTINATION_BCD_X; 907 | 908 | case INSTRUCTION_OR: 909 | case INSTRUCTION_SUB: 910 | case INSTRUCTION_AND: 911 | case INSTRUCTION_ADD: 912 | return INSTRUCTION_DESTINATION_DATA_REGISTER_SECONDARY_OR_PRIMARY_ADDRESS_MODE; 913 | 914 | case INSTRUCTION_MOVEA: 915 | return INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY_FULL; 916 | 917 | case INSTRUCTION_CMPM: 918 | return INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY_POSTINCREMENT; 919 | 920 | case INSTRUCTION_ORI: 921 | case INSTRUCTION_ANDI: 922 | case INSTRUCTION_SUBI: 923 | case INSTRUCTION_ADDI: 924 | case INSTRUCTION_EORI: 925 | case INSTRUCTION_CMPI: 926 | case INSTRUCTION_BTST_STATIC: 927 | case INSTRUCTION_BCHG_STATIC: 928 | case INSTRUCTION_BCLR_STATIC: 929 | case INSTRUCTION_BSET_STATIC: 930 | case INSTRUCTION_BTST_DYNAMIC: 931 | case INSTRUCTION_BCHG_DYNAMIC: 932 | case INSTRUCTION_BCLR_DYNAMIC: 933 | case INSTRUCTION_BSET_DYNAMIC: 934 | case INSTRUCTION_NEGX: 935 | case INSTRUCTION_NEG: 936 | case INSTRUCTION_NOT: 937 | case INSTRUCTION_NBCD: 938 | case INSTRUCTION_TAS: 939 | case INSTRUCTION_MOVE_FROM_SR: 940 | case INSTRUCTION_CLR: 941 | case INSTRUCTION_ADDAQ: 942 | case INSTRUCTION_SUBAQ: 943 | case INSTRUCTION_ADDQ: 944 | case INSTRUCTION_SUBQ: 945 | case INSTRUCTION_SCC: 946 | case INSTRUCTION_EOR: 947 | case INSTRUCTION_ASD_MEMORY: 948 | case INSTRUCTION_LSD_MEMORY: 949 | case INSTRUCTION_ROXD_MEMORY: 950 | case INSTRUCTION_ROD_MEMORY: 951 | return INSTRUCTION_DESTINATION_PRIMARY_ADDRESS_MODE; 952 | 953 | case INSTRUCTION_ORI_TO_CCR: 954 | case INSTRUCTION_ANDI_TO_CCR: 955 | case INSTRUCTION_EORI_TO_CCR: 956 | case INSTRUCTION_MOVE_TO_CCR: 957 | return INSTRUCTION_DESTINATION_CONDITION_CODE_REGISTER; 958 | 959 | case INSTRUCTION_ORI_TO_SR: 960 | case INSTRUCTION_ANDI_TO_SR: 961 | case INSTRUCTION_EORI_TO_SR: 962 | case INSTRUCTION_MOVE_TO_SR: 963 | return INSTRUCTION_DESTINATION_STATUS_REGISTER; 964 | 965 | case INSTRUCTION_MOVEM: 966 | return INSTRUCTION_DESTINATION_MOVEM; 967 | 968 | case INSTRUCTION_MOVEP: 969 | return INSTRUCTION_DESTINATION_MOVEP; 970 | 971 | case INSTRUCTION_PEA: 972 | case INSTRUCTION_ILLEGAL: 973 | case INSTRUCTION_TRAP: 974 | case INSTRUCTION_LINK: 975 | case INSTRUCTION_UNLK: 976 | case INSTRUCTION_MOVE_USP: 977 | case INSTRUCTION_RESET: 978 | case INSTRUCTION_NOP: 979 | case INSTRUCTION_STOP: 980 | case INSTRUCTION_RTE: 981 | case INSTRUCTION_RTS: 982 | case INSTRUCTION_TRAPV: 983 | case INSTRUCTION_RTR: 984 | case INSTRUCTION_JSR: 985 | case INSTRUCTION_JMP: 986 | case INSTRUCTION_CHK: 987 | case INSTRUCTION_DBCC: 988 | case INSTRUCTION_BRA_SHORT: 989 | case INSTRUCTION_BRA_WORD: 990 | case INSTRUCTION_BSR_SHORT: 991 | case INSTRUCTION_BSR_WORD: 992 | case INSTRUCTION_BCC_SHORT: 993 | case INSTRUCTION_BCC_WORD: 994 | case INSTRUCTION_EXG: 995 | case INSTRUCTION_TST: 996 | case INSTRUCTION_UNIMPLEMENTED_1: 997 | case INSTRUCTION_UNIMPLEMENTED_2: 998 | return INSTRUCTION_DESTINATION_NONE; 999 | } 1000 | 1001 | assert(cc_false); 1002 | 1003 | return INSTRUCTION_DESTINATION_NONE; 1004 | } 1005 | 1006 | InstructionCarry Instruction_GetCarryModifier(const Instruction instruction) 1007 | { 1008 | switch (instruction) 1009 | { 1010 | case INSTRUCTION_ADDQ: 1011 | case INSTRUCTION_ADD: 1012 | case INSTRUCTION_ADDI: 1013 | case INSTRUCTION_ADDX: 1014 | return INSTRUCTION_CARRY_STANDARD_CARRY; 1015 | 1016 | case INSTRUCTION_SUBQ: 1017 | case INSTRUCTION_CMP: 1018 | case INSTRUCTION_CMPA: 1019 | case INSTRUCTION_CMPI: 1020 | case INSTRUCTION_CMPM: 1021 | case INSTRUCTION_SUB: 1022 | case INSTRUCTION_SUBI: 1023 | case INSTRUCTION_SUBX: 1024 | return INSTRUCTION_CARRY_STANDARD_BORROW; 1025 | 1026 | case INSTRUCTION_NEG: 1027 | case INSTRUCTION_NEGX: 1028 | return INSTRUCTION_CARRY_NEG; 1029 | 1030 | case INSTRUCTION_AND: 1031 | case INSTRUCTION_ANDI: 1032 | case INSTRUCTION_EOR: 1033 | case INSTRUCTION_EORI: 1034 | case INSTRUCTION_MOVEQ: 1035 | case INSTRUCTION_MOVE: 1036 | case INSTRUCTION_OR: 1037 | case INSTRUCTION_ORI: 1038 | case INSTRUCTION_CLR: 1039 | case INSTRUCTION_EXT: 1040 | case INSTRUCTION_NOT: 1041 | case INSTRUCTION_TAS: 1042 | case INSTRUCTION_TST: 1043 | case INSTRUCTION_DIVS: 1044 | case INSTRUCTION_DIVU: 1045 | case INSTRUCTION_MULS: 1046 | case INSTRUCTION_MULU: 1047 | case INSTRUCTION_SWAP: 1048 | return INSTRUCTION_CARRY_CLEAR; 1049 | 1050 | case INSTRUCTION_CHK: 1051 | return INSTRUCTION_CARRY_UNDEFINED; 1052 | 1053 | case INSTRUCTION_ABCD: 1054 | case INSTRUCTION_NBCD: 1055 | case INSTRUCTION_SBCD: 1056 | /* The above three set their carry code manually. */ 1057 | case INSTRUCTION_ASD_REGISTER: 1058 | case INSTRUCTION_ASD_MEMORY: 1059 | case INSTRUCTION_LSD_REGISTER: 1060 | case INSTRUCTION_LSD_MEMORY: 1061 | case INSTRUCTION_ROD_REGISTER: 1062 | case INSTRUCTION_ROD_MEMORY: 1063 | case INSTRUCTION_ROXD_REGISTER: 1064 | case INSTRUCTION_ROXD_MEMORY: 1065 | case INSTRUCTION_ADDA: 1066 | case INSTRUCTION_ADDAQ: 1067 | case INSTRUCTION_ANDI_TO_CCR: 1068 | case INSTRUCTION_ANDI_TO_SR: 1069 | case INSTRUCTION_BCC_SHORT: 1070 | case INSTRUCTION_BCC_WORD: 1071 | case INSTRUCTION_BCHG_DYNAMIC: 1072 | case INSTRUCTION_BCHG_STATIC: 1073 | case INSTRUCTION_BCLR_DYNAMIC: 1074 | case INSTRUCTION_BCLR_STATIC: 1075 | case INSTRUCTION_BRA_SHORT: 1076 | case INSTRUCTION_BRA_WORD: 1077 | case INSTRUCTION_BSET_DYNAMIC: 1078 | case INSTRUCTION_BSET_STATIC: 1079 | case INSTRUCTION_BSR_SHORT: 1080 | case INSTRUCTION_BSR_WORD: 1081 | case INSTRUCTION_BTST_DYNAMIC: 1082 | case INSTRUCTION_BTST_STATIC: 1083 | case INSTRUCTION_DBCC: 1084 | case INSTRUCTION_EORI_TO_CCR: 1085 | case INSTRUCTION_EORI_TO_SR: 1086 | case INSTRUCTION_EXG: 1087 | case INSTRUCTION_JMP: 1088 | case INSTRUCTION_JSR: 1089 | case INSTRUCTION_ILLEGAL: 1090 | case INSTRUCTION_LEA: 1091 | case INSTRUCTION_LINK: 1092 | case INSTRUCTION_MOVE_FROM_SR: 1093 | case INSTRUCTION_MOVE_TO_CCR: 1094 | case INSTRUCTION_MOVE_TO_SR: 1095 | case INSTRUCTION_MOVE_USP: 1096 | case INSTRUCTION_MOVEA: 1097 | case INSTRUCTION_MOVEM: 1098 | case INSTRUCTION_MOVEP: 1099 | case INSTRUCTION_NOP: 1100 | case INSTRUCTION_ORI_TO_CCR: 1101 | case INSTRUCTION_ORI_TO_SR: 1102 | case INSTRUCTION_PEA: 1103 | case INSTRUCTION_RESET: 1104 | case INSTRUCTION_RTE: 1105 | case INSTRUCTION_RTR: 1106 | case INSTRUCTION_RTS: 1107 | case INSTRUCTION_SCC: 1108 | case INSTRUCTION_STOP: 1109 | case INSTRUCTION_SUBA: 1110 | case INSTRUCTION_SUBAQ: 1111 | case INSTRUCTION_TRAP: 1112 | case INSTRUCTION_TRAPV: 1113 | case INSTRUCTION_UNLK: 1114 | case INSTRUCTION_UNIMPLEMENTED_1: 1115 | case INSTRUCTION_UNIMPLEMENTED_2: 1116 | return INSTRUCTION_CARRY_UNAFFECTED; 1117 | } 1118 | 1119 | assert(cc_false); 1120 | 1121 | return INSTRUCTION_CARRY_UNAFFECTED; 1122 | } 1123 | 1124 | InstructionOverflow Instruction_GetOverflowModifier(const Instruction instruction) 1125 | { 1126 | switch (instruction) 1127 | { 1128 | case INSTRUCTION_ABCD: 1129 | case INSTRUCTION_ADDQ: 1130 | case INSTRUCTION_ADD: 1131 | case INSTRUCTION_ADDI: 1132 | case INSTRUCTION_ADDX: 1133 | return INSTRUCTION_OVERFLOW_ADD; 1134 | 1135 | case INSTRUCTION_SUBQ: 1136 | case INSTRUCTION_CMP: 1137 | case INSTRUCTION_CMPA: 1138 | case INSTRUCTION_CMPI: 1139 | case INSTRUCTION_CMPM: 1140 | case INSTRUCTION_NBCD: 1141 | case INSTRUCTION_SBCD: 1142 | case INSTRUCTION_SUB: 1143 | case INSTRUCTION_SUBI: 1144 | case INSTRUCTION_SUBX: 1145 | return INSTRUCTION_OVERFLOW_SUB; 1146 | 1147 | case INSTRUCTION_NEG: 1148 | case INSTRUCTION_NEGX: 1149 | return INSTRUCTION_OVERFLOW_NEG; 1150 | 1151 | case INSTRUCTION_AND: 1152 | case INSTRUCTION_ANDI: 1153 | case INSTRUCTION_CLR: 1154 | case INSTRUCTION_EOR: 1155 | case INSTRUCTION_EORI: 1156 | case INSTRUCTION_EXT: 1157 | case INSTRUCTION_MOVE: 1158 | case INSTRUCTION_MOVEQ: 1159 | case INSTRUCTION_MULS: 1160 | case INSTRUCTION_MULU: 1161 | case INSTRUCTION_NOT: 1162 | case INSTRUCTION_OR: 1163 | case INSTRUCTION_ORI: 1164 | case INSTRUCTION_SWAP: 1165 | case INSTRUCTION_TAS: 1166 | case INSTRUCTION_TST: 1167 | return INSTRUCTION_OVERFLOW_CLEARED; 1168 | 1169 | case INSTRUCTION_CHK: 1170 | return INSTRUCTION_OVERFLOW_UNDEFINED; 1171 | 1172 | case INSTRUCTION_ASD_REGISTER: 1173 | case INSTRUCTION_ASD_MEMORY: 1174 | case INSTRUCTION_DIVS: 1175 | case INSTRUCTION_DIVU: 1176 | case INSTRUCTION_LSD_REGISTER: 1177 | case INSTRUCTION_LSD_MEMORY: 1178 | case INSTRUCTION_ROD_REGISTER: 1179 | case INSTRUCTION_ROD_MEMORY: 1180 | case INSTRUCTION_ROXD_REGISTER: 1181 | case INSTRUCTION_ROXD_MEMORY: 1182 | case INSTRUCTION_ADDA: 1183 | case INSTRUCTION_ADDAQ: 1184 | case INSTRUCTION_ANDI_TO_CCR: 1185 | case INSTRUCTION_ANDI_TO_SR: 1186 | case INSTRUCTION_BCC_SHORT: 1187 | case INSTRUCTION_BCC_WORD: 1188 | case INSTRUCTION_BCHG_DYNAMIC: 1189 | case INSTRUCTION_BCHG_STATIC: 1190 | case INSTRUCTION_BCLR_DYNAMIC: 1191 | case INSTRUCTION_BCLR_STATIC: 1192 | case INSTRUCTION_BRA_SHORT: 1193 | case INSTRUCTION_BRA_WORD: 1194 | case INSTRUCTION_BSET_DYNAMIC: 1195 | case INSTRUCTION_BSET_STATIC: 1196 | case INSTRUCTION_BSR_SHORT: 1197 | case INSTRUCTION_BSR_WORD: 1198 | case INSTRUCTION_BTST_DYNAMIC: 1199 | case INSTRUCTION_BTST_STATIC: 1200 | case INSTRUCTION_DBCC: 1201 | case INSTRUCTION_EORI_TO_CCR: 1202 | case INSTRUCTION_EORI_TO_SR: 1203 | case INSTRUCTION_EXG: 1204 | case INSTRUCTION_JMP: 1205 | case INSTRUCTION_JSR: 1206 | case INSTRUCTION_ILLEGAL: 1207 | case INSTRUCTION_LEA: 1208 | case INSTRUCTION_LINK: 1209 | case INSTRUCTION_MOVE_FROM_SR: 1210 | case INSTRUCTION_MOVE_TO_CCR: 1211 | case INSTRUCTION_MOVE_TO_SR: 1212 | case INSTRUCTION_MOVE_USP: 1213 | case INSTRUCTION_MOVEA: 1214 | case INSTRUCTION_MOVEM: 1215 | case INSTRUCTION_MOVEP: 1216 | case INSTRUCTION_NOP: 1217 | case INSTRUCTION_ORI_TO_CCR: 1218 | case INSTRUCTION_ORI_TO_SR: 1219 | case INSTRUCTION_PEA: 1220 | case INSTRUCTION_RESET: 1221 | case INSTRUCTION_RTE: 1222 | case INSTRUCTION_RTR: 1223 | case INSTRUCTION_RTS: 1224 | case INSTRUCTION_SCC: 1225 | case INSTRUCTION_STOP: 1226 | case INSTRUCTION_SUBA: 1227 | case INSTRUCTION_SUBAQ: 1228 | case INSTRUCTION_TRAP: 1229 | case INSTRUCTION_TRAPV: 1230 | case INSTRUCTION_UNLK: 1231 | case INSTRUCTION_UNIMPLEMENTED_1: 1232 | case INSTRUCTION_UNIMPLEMENTED_2: 1233 | return INSTRUCTION_OVERFLOW_UNAFFECTED; 1234 | } 1235 | 1236 | assert(cc_false); 1237 | 1238 | return INSTRUCTION_OVERFLOW_UNAFFECTED; 1239 | } 1240 | 1241 | InstructionZero Instruction_GetZeroModifier(const Instruction instruction) 1242 | { 1243 | switch (instruction) 1244 | { 1245 | case INSTRUCTION_ABCD: 1246 | case INSTRUCTION_ADDX: 1247 | case INSTRUCTION_NBCD: 1248 | case INSTRUCTION_NEGX: 1249 | case INSTRUCTION_SBCD: 1250 | case INSTRUCTION_SUBX: 1251 | return INSTRUCTION_ZERO_CLEAR_IF_NONZERO_UNAFFECTED_OTHERWISE; 1252 | 1253 | case INSTRUCTION_ADDQ: 1254 | case INSTRUCTION_SUBQ: 1255 | case INSTRUCTION_ADD: 1256 | case INSTRUCTION_ADDI: 1257 | case INSTRUCTION_AND: 1258 | case INSTRUCTION_ANDI: 1259 | case INSTRUCTION_ASD_REGISTER: 1260 | case INSTRUCTION_ASD_MEMORY: 1261 | case INSTRUCTION_CLR: 1262 | case INSTRUCTION_CMP: 1263 | case INSTRUCTION_CMPA: 1264 | case INSTRUCTION_CMPI: 1265 | case INSTRUCTION_CMPM: 1266 | case INSTRUCTION_EOR: 1267 | case INSTRUCTION_EORI: 1268 | case INSTRUCTION_EXT: 1269 | case INSTRUCTION_LSD_REGISTER: 1270 | case INSTRUCTION_LSD_MEMORY: 1271 | case INSTRUCTION_MOVE: 1272 | case INSTRUCTION_MOVEQ: 1273 | case INSTRUCTION_MULS: 1274 | case INSTRUCTION_MULU: 1275 | case INSTRUCTION_NEG: 1276 | case INSTRUCTION_NOT: 1277 | case INSTRUCTION_OR: 1278 | case INSTRUCTION_ORI: 1279 | case INSTRUCTION_ROD_REGISTER: 1280 | case INSTRUCTION_ROD_MEMORY: 1281 | case INSTRUCTION_ROXD_REGISTER: 1282 | case INSTRUCTION_ROXD_MEMORY: 1283 | case INSTRUCTION_SUB: 1284 | case INSTRUCTION_SUBI: 1285 | case INSTRUCTION_SWAP: 1286 | case INSTRUCTION_TST: 1287 | return INSTRUCTION_ZERO_SET_IF_ZERO_CLEAR_OTHERWISE; 1288 | 1289 | case INSTRUCTION_CHK: 1290 | return INSTRUCTION_ZERO_UNDEFINED; 1291 | 1292 | case INSTRUCTION_DIVS: 1293 | case INSTRUCTION_DIVU: 1294 | case INSTRUCTION_TAS: 1295 | case INSTRUCTION_ADDA: 1296 | case INSTRUCTION_ADDAQ: 1297 | case INSTRUCTION_ANDI_TO_CCR: 1298 | case INSTRUCTION_ANDI_TO_SR: 1299 | case INSTRUCTION_BCC_SHORT: 1300 | case INSTRUCTION_BCC_WORD: 1301 | case INSTRUCTION_BCHG_DYNAMIC: 1302 | case INSTRUCTION_BCHG_STATIC: 1303 | case INSTRUCTION_BCLR_DYNAMIC: 1304 | case INSTRUCTION_BCLR_STATIC: 1305 | case INSTRUCTION_BRA_SHORT: 1306 | case INSTRUCTION_BRA_WORD: 1307 | case INSTRUCTION_BSET_DYNAMIC: 1308 | case INSTRUCTION_BSET_STATIC: 1309 | case INSTRUCTION_BSR_SHORT: 1310 | case INSTRUCTION_BSR_WORD: 1311 | case INSTRUCTION_BTST_DYNAMIC: 1312 | case INSTRUCTION_BTST_STATIC: 1313 | case INSTRUCTION_DBCC: 1314 | case INSTRUCTION_EORI_TO_CCR: 1315 | case INSTRUCTION_EORI_TO_SR: 1316 | case INSTRUCTION_EXG: 1317 | case INSTRUCTION_JMP: 1318 | case INSTRUCTION_JSR: 1319 | case INSTRUCTION_ILLEGAL: 1320 | case INSTRUCTION_LEA: 1321 | case INSTRUCTION_LINK: 1322 | case INSTRUCTION_MOVE_FROM_SR: 1323 | case INSTRUCTION_MOVE_TO_CCR: 1324 | case INSTRUCTION_MOVE_TO_SR: 1325 | case INSTRUCTION_MOVE_USP: 1326 | case INSTRUCTION_MOVEA: 1327 | case INSTRUCTION_MOVEM: 1328 | case INSTRUCTION_MOVEP: 1329 | case INSTRUCTION_NOP: 1330 | case INSTRUCTION_ORI_TO_CCR: 1331 | case INSTRUCTION_ORI_TO_SR: 1332 | case INSTRUCTION_PEA: 1333 | case INSTRUCTION_RESET: 1334 | case INSTRUCTION_RTE: 1335 | case INSTRUCTION_RTR: 1336 | case INSTRUCTION_RTS: 1337 | case INSTRUCTION_SCC: 1338 | case INSTRUCTION_STOP: 1339 | case INSTRUCTION_SUBA: 1340 | case INSTRUCTION_SUBAQ: 1341 | case INSTRUCTION_TRAP: 1342 | case INSTRUCTION_TRAPV: 1343 | case INSTRUCTION_UNLK: 1344 | case INSTRUCTION_UNIMPLEMENTED_1: 1345 | case INSTRUCTION_UNIMPLEMENTED_2: 1346 | return INSTRUCTION_ZERO_UNAFFECTED; 1347 | } 1348 | 1349 | assert(cc_false); 1350 | 1351 | return INSTRUCTION_ZERO_UNAFFECTED; 1352 | } 1353 | 1354 | InstructionNegative Instruction_GetNegativeModifier(const Instruction instruction) 1355 | { 1356 | switch (instruction) 1357 | { 1358 | case INSTRUCTION_ABCD: 1359 | case INSTRUCTION_NBCD: 1360 | case INSTRUCTION_SBCD: 1361 | case INSTRUCTION_ADDQ: 1362 | case INSTRUCTION_SUBQ: 1363 | case INSTRUCTION_ADD: 1364 | case INSTRUCTION_ADDI: 1365 | case INSTRUCTION_ADDX: 1366 | case INSTRUCTION_AND: 1367 | case INSTRUCTION_ANDI: 1368 | case INSTRUCTION_ASD_REGISTER: 1369 | case INSTRUCTION_ASD_MEMORY: 1370 | case INSTRUCTION_CLR: 1371 | case INSTRUCTION_CMP: 1372 | case INSTRUCTION_CMPA: 1373 | case INSTRUCTION_CMPI: 1374 | case INSTRUCTION_CMPM: 1375 | case INSTRUCTION_EOR: 1376 | case INSTRUCTION_EORI: 1377 | case INSTRUCTION_EXT: 1378 | case INSTRUCTION_LSD_REGISTER: 1379 | case INSTRUCTION_LSD_MEMORY: 1380 | case INSTRUCTION_MOVE: 1381 | case INSTRUCTION_MOVEQ: 1382 | case INSTRUCTION_MULS: 1383 | case INSTRUCTION_MULU: 1384 | case INSTRUCTION_NEG: 1385 | case INSTRUCTION_NEGX: 1386 | case INSTRUCTION_NOT: 1387 | case INSTRUCTION_OR: 1388 | case INSTRUCTION_ORI: 1389 | case INSTRUCTION_ROD_REGISTER: 1390 | case INSTRUCTION_ROD_MEMORY: 1391 | case INSTRUCTION_ROXD_REGISTER: 1392 | case INSTRUCTION_ROXD_MEMORY: 1393 | case INSTRUCTION_SUB: 1394 | case INSTRUCTION_SUBI: 1395 | case INSTRUCTION_SUBX: 1396 | case INSTRUCTION_SWAP: 1397 | case INSTRUCTION_TST: 1398 | return INSTRUCTION_NEGATIVE_SET_IF_NEGATIVE_CLEAR_OTHERWISE; 1399 | 1400 | case INSTRUCTION_CHK: 1401 | case INSTRUCTION_DIVS: 1402 | case INSTRUCTION_DIVU: 1403 | case INSTRUCTION_TAS: 1404 | case INSTRUCTION_ADDA: 1405 | case INSTRUCTION_ADDAQ: 1406 | case INSTRUCTION_ANDI_TO_CCR: 1407 | case INSTRUCTION_ANDI_TO_SR: 1408 | case INSTRUCTION_BCC_SHORT: 1409 | case INSTRUCTION_BCC_WORD: 1410 | case INSTRUCTION_BCHG_DYNAMIC: 1411 | case INSTRUCTION_BCHG_STATIC: 1412 | case INSTRUCTION_BCLR_DYNAMIC: 1413 | case INSTRUCTION_BCLR_STATIC: 1414 | case INSTRUCTION_BRA_SHORT: 1415 | case INSTRUCTION_BRA_WORD: 1416 | case INSTRUCTION_BSET_DYNAMIC: 1417 | case INSTRUCTION_BSET_STATIC: 1418 | case INSTRUCTION_BSR_SHORT: 1419 | case INSTRUCTION_BSR_WORD: 1420 | case INSTRUCTION_BTST_DYNAMIC: 1421 | case INSTRUCTION_BTST_STATIC: 1422 | case INSTRUCTION_DBCC: 1423 | case INSTRUCTION_EORI_TO_CCR: 1424 | case INSTRUCTION_EORI_TO_SR: 1425 | case INSTRUCTION_EXG: 1426 | case INSTRUCTION_JMP: 1427 | case INSTRUCTION_JSR: 1428 | case INSTRUCTION_ILLEGAL: 1429 | case INSTRUCTION_LEA: 1430 | case INSTRUCTION_LINK: 1431 | case INSTRUCTION_MOVE_FROM_SR: 1432 | case INSTRUCTION_MOVE_TO_CCR: 1433 | case INSTRUCTION_MOVE_TO_SR: 1434 | case INSTRUCTION_MOVE_USP: 1435 | case INSTRUCTION_MOVEA: 1436 | case INSTRUCTION_MOVEM: 1437 | case INSTRUCTION_MOVEP: 1438 | case INSTRUCTION_NOP: 1439 | case INSTRUCTION_ORI_TO_CCR: 1440 | case INSTRUCTION_ORI_TO_SR: 1441 | case INSTRUCTION_PEA: 1442 | case INSTRUCTION_RESET: 1443 | case INSTRUCTION_RTE: 1444 | case INSTRUCTION_RTR: 1445 | case INSTRUCTION_RTS: 1446 | case INSTRUCTION_SCC: 1447 | case INSTRUCTION_STOP: 1448 | case INSTRUCTION_SUBA: 1449 | case INSTRUCTION_SUBAQ: 1450 | case INSTRUCTION_TRAP: 1451 | case INSTRUCTION_TRAPV: 1452 | case INSTRUCTION_UNLK: 1453 | case INSTRUCTION_UNIMPLEMENTED_1: 1454 | case INSTRUCTION_UNIMPLEMENTED_2: 1455 | return INSTRUCTION_NEGATIVE_UNAFFECTED; 1456 | } 1457 | 1458 | assert(cc_false); 1459 | 1460 | return INSTRUCTION_NEGATIVE_UNAFFECTED; 1461 | } 1462 | 1463 | InstructionExtend Instruction_GetExtendModifier(const Instruction instruction) 1464 | { 1465 | switch (instruction) 1466 | { 1467 | case INSTRUCTION_ADDQ: 1468 | case INSTRUCTION_SUBQ: 1469 | case INSTRUCTION_ABCD: 1470 | case INSTRUCTION_ADD: 1471 | case INSTRUCTION_ADDI: 1472 | case INSTRUCTION_ADDX: 1473 | case INSTRUCTION_NBCD: 1474 | case INSTRUCTION_NEG: 1475 | case INSTRUCTION_NEGX: 1476 | case INSTRUCTION_SBCD: 1477 | case INSTRUCTION_SUB: 1478 | case INSTRUCTION_SUBI: 1479 | case INSTRUCTION_SUBX: 1480 | return INSTRUCTION_EXTEND_SET_TO_CARRY; 1481 | 1482 | case INSTRUCTION_AND: 1483 | case INSTRUCTION_ANDI: 1484 | case INSTRUCTION_CLR: 1485 | case INSTRUCTION_CHK: 1486 | case INSTRUCTION_CMP: 1487 | case INSTRUCTION_CMPA: 1488 | case INSTRUCTION_CMPI: 1489 | case INSTRUCTION_CMPM: 1490 | case INSTRUCTION_EOR: 1491 | case INSTRUCTION_EORI: 1492 | case INSTRUCTION_EXT: 1493 | case INSTRUCTION_MOVE: 1494 | case INSTRUCTION_MOVEQ: 1495 | case INSTRUCTION_NOT: 1496 | case INSTRUCTION_OR: 1497 | case INSTRUCTION_ORI: 1498 | case INSTRUCTION_SWAP: 1499 | case INSTRUCTION_TAS: 1500 | case INSTRUCTION_TST: 1501 | case INSTRUCTION_ASD_REGISTER: 1502 | case INSTRUCTION_ASD_MEMORY: 1503 | case INSTRUCTION_DIVS: 1504 | case INSTRUCTION_DIVU: 1505 | case INSTRUCTION_LSD_REGISTER: 1506 | case INSTRUCTION_LSD_MEMORY: 1507 | case INSTRUCTION_MULS: 1508 | case INSTRUCTION_MULU: 1509 | case INSTRUCTION_ROD_REGISTER: 1510 | case INSTRUCTION_ROD_MEMORY: 1511 | case INSTRUCTION_ROXD_REGISTER: 1512 | case INSTRUCTION_ROXD_MEMORY: 1513 | case INSTRUCTION_ADDA: 1514 | case INSTRUCTION_ADDAQ: 1515 | case INSTRUCTION_ANDI_TO_CCR: 1516 | case INSTRUCTION_ANDI_TO_SR: 1517 | case INSTRUCTION_BCC_SHORT: 1518 | case INSTRUCTION_BCC_WORD: 1519 | case INSTRUCTION_BCHG_DYNAMIC: 1520 | case INSTRUCTION_BCHG_STATIC: 1521 | case INSTRUCTION_BCLR_DYNAMIC: 1522 | case INSTRUCTION_BCLR_STATIC: 1523 | case INSTRUCTION_BRA_SHORT: 1524 | case INSTRUCTION_BRA_WORD: 1525 | case INSTRUCTION_BSET_DYNAMIC: 1526 | case INSTRUCTION_BSET_STATIC: 1527 | case INSTRUCTION_BSR_SHORT: 1528 | case INSTRUCTION_BSR_WORD: 1529 | case INSTRUCTION_BTST_DYNAMIC: 1530 | case INSTRUCTION_BTST_STATIC: 1531 | case INSTRUCTION_DBCC: 1532 | case INSTRUCTION_EORI_TO_CCR: 1533 | case INSTRUCTION_EORI_TO_SR: 1534 | case INSTRUCTION_EXG: 1535 | case INSTRUCTION_JMP: 1536 | case INSTRUCTION_JSR: 1537 | case INSTRUCTION_ILLEGAL: 1538 | case INSTRUCTION_LEA: 1539 | case INSTRUCTION_LINK: 1540 | case INSTRUCTION_MOVE_FROM_SR: 1541 | case INSTRUCTION_MOVE_TO_CCR: 1542 | case INSTRUCTION_MOVE_TO_SR: 1543 | case INSTRUCTION_MOVE_USP: 1544 | case INSTRUCTION_MOVEA: 1545 | case INSTRUCTION_MOVEM: 1546 | case INSTRUCTION_MOVEP: 1547 | case INSTRUCTION_NOP: 1548 | case INSTRUCTION_ORI_TO_CCR: 1549 | case INSTRUCTION_ORI_TO_SR: 1550 | case INSTRUCTION_PEA: 1551 | case INSTRUCTION_RESET: 1552 | case INSTRUCTION_RTE: 1553 | case INSTRUCTION_RTR: 1554 | case INSTRUCTION_RTS: 1555 | case INSTRUCTION_SCC: 1556 | case INSTRUCTION_STOP: 1557 | case INSTRUCTION_SUBA: 1558 | case INSTRUCTION_SUBAQ: 1559 | case INSTRUCTION_TRAP: 1560 | case INSTRUCTION_TRAPV: 1561 | case INSTRUCTION_UNLK: 1562 | case INSTRUCTION_UNIMPLEMENTED_1: 1563 | case INSTRUCTION_UNIMPLEMENTED_2: 1564 | return INSTRUCTION_EXTEND_UNAFFECTED; 1565 | } 1566 | 1567 | assert(cc_false); 1568 | 1569 | return INSTRUCTION_EXTEND_UNAFFECTED; 1570 | } 1571 | 1572 | cc_bool Instruction_IsPrivileged(const Instruction instruction) 1573 | { 1574 | switch (instruction) 1575 | { 1576 | case INSTRUCTION_ANDI_TO_SR: 1577 | case INSTRUCTION_EORI_TO_SR: 1578 | case INSTRUCTION_MOVE_TO_SR: 1579 | case INSTRUCTION_MOVE_USP: 1580 | case INSTRUCTION_ORI_TO_SR: 1581 | case INSTRUCTION_RESET: 1582 | case INSTRUCTION_RTE: 1583 | case INSTRUCTION_STOP: 1584 | return cc_true; 1585 | 1586 | case INSTRUCTION_AND: 1587 | case INSTRUCTION_ANDI: 1588 | case INSTRUCTION_CLR: 1589 | case INSTRUCTION_CHK: 1590 | case INSTRUCTION_CMP: 1591 | case INSTRUCTION_CMPA: 1592 | case INSTRUCTION_CMPI: 1593 | case INSTRUCTION_CMPM: 1594 | case INSTRUCTION_EOR: 1595 | case INSTRUCTION_EORI: 1596 | case INSTRUCTION_EXT: 1597 | case INSTRUCTION_MOVE: 1598 | case INSTRUCTION_MOVEQ: 1599 | case INSTRUCTION_NOT: 1600 | case INSTRUCTION_OR: 1601 | case INSTRUCTION_ORI: 1602 | case INSTRUCTION_SWAP: 1603 | case INSTRUCTION_TAS: 1604 | case INSTRUCTION_TST: 1605 | case INSTRUCTION_ASD_REGISTER: 1606 | case INSTRUCTION_ASD_MEMORY: 1607 | case INSTRUCTION_DIVS: 1608 | case INSTRUCTION_DIVU: 1609 | case INSTRUCTION_LSD_REGISTER: 1610 | case INSTRUCTION_LSD_MEMORY: 1611 | case INSTRUCTION_MULS: 1612 | case INSTRUCTION_MULU: 1613 | case INSTRUCTION_ROD_REGISTER: 1614 | case INSTRUCTION_ROD_MEMORY: 1615 | case INSTRUCTION_ROXD_REGISTER: 1616 | case INSTRUCTION_ROXD_MEMORY: 1617 | case INSTRUCTION_ADDQ: 1618 | case INSTRUCTION_SUBQ: 1619 | case INSTRUCTION_ABCD: 1620 | case INSTRUCTION_ADD: 1621 | case INSTRUCTION_ADDI: 1622 | case INSTRUCTION_ADDX: 1623 | case INSTRUCTION_NBCD: 1624 | case INSTRUCTION_NEG: 1625 | case INSTRUCTION_NEGX: 1626 | case INSTRUCTION_SBCD: 1627 | case INSTRUCTION_SUB: 1628 | case INSTRUCTION_SUBI: 1629 | case INSTRUCTION_SUBX: 1630 | case INSTRUCTION_ADDA: 1631 | case INSTRUCTION_ADDAQ: 1632 | case INSTRUCTION_ANDI_TO_CCR: 1633 | case INSTRUCTION_BCC_SHORT: 1634 | case INSTRUCTION_BCC_WORD: 1635 | case INSTRUCTION_BCHG_DYNAMIC: 1636 | case INSTRUCTION_BCHG_STATIC: 1637 | case INSTRUCTION_BCLR_DYNAMIC: 1638 | case INSTRUCTION_BCLR_STATIC: 1639 | case INSTRUCTION_BRA_SHORT: 1640 | case INSTRUCTION_BRA_WORD: 1641 | case INSTRUCTION_BSET_DYNAMIC: 1642 | case INSTRUCTION_BSET_STATIC: 1643 | case INSTRUCTION_BSR_SHORT: 1644 | case INSTRUCTION_BSR_WORD: 1645 | case INSTRUCTION_BTST_DYNAMIC: 1646 | case INSTRUCTION_BTST_STATIC: 1647 | case INSTRUCTION_DBCC: 1648 | case INSTRUCTION_EORI_TO_CCR: 1649 | case INSTRUCTION_EXG: 1650 | case INSTRUCTION_JMP: 1651 | case INSTRUCTION_JSR: 1652 | case INSTRUCTION_ILLEGAL: 1653 | case INSTRUCTION_LEA: 1654 | case INSTRUCTION_LINK: 1655 | case INSTRUCTION_MOVE_FROM_SR: 1656 | case INSTRUCTION_MOVE_TO_CCR: 1657 | case INSTRUCTION_MOVEA: 1658 | case INSTRUCTION_MOVEM: 1659 | case INSTRUCTION_MOVEP: 1660 | case INSTRUCTION_NOP: 1661 | case INSTRUCTION_ORI_TO_CCR: 1662 | case INSTRUCTION_PEA: 1663 | case INSTRUCTION_RTR: 1664 | case INSTRUCTION_RTS: 1665 | case INSTRUCTION_SCC: 1666 | case INSTRUCTION_SUBA: 1667 | case INSTRUCTION_SUBAQ: 1668 | case INSTRUCTION_TRAP: 1669 | case INSTRUCTION_TRAPV: 1670 | case INSTRUCTION_UNLK: 1671 | case INSTRUCTION_UNIMPLEMENTED_1: 1672 | case INSTRUCTION_UNIMPLEMENTED_2: 1673 | return cc_false; 1674 | } 1675 | 1676 | assert(cc_false); 1677 | 1678 | return cc_false; 1679 | } 1680 | -------------------------------------------------------------------------------- /interpreter/microcode-generator/instruction-properties.h: -------------------------------------------------------------------------------- 1 | /* 2 | clown68000 - A Motorola 68000 emulator. 3 | Copyright (C) 2021-2023 Clownacy 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 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 Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INCLUDE_GUARD_FB923D67_894A_4DE9_A848_05748F0BFEE7 20 | #define INCLUDE_GUARD_FB923D67_894A_4DE9_A848_05748F0BFEE7 21 | 22 | #include "../../common/clowncommon/clowncommon.h" 23 | 24 | #include "../../common/instruction.h" 25 | 26 | typedef enum InstructionAction 27 | { 28 | INSTRUCTION_ACTION_OR, 29 | INSTRUCTION_ACTION_AND, 30 | INSTRUCTION_ACTION_CMPA, 31 | INSTRUCTION_ACTION_CMP, 32 | INSTRUCTION_ACTION_CMPM, 33 | INSTRUCTION_ACTION_CMPI, 34 | INSTRUCTION_ACTION_SUBA, 35 | INSTRUCTION_ACTION_SUBQ, 36 | INSTRUCTION_ACTION_SUB, 37 | INSTRUCTION_ACTION_ADDA, 38 | INSTRUCTION_ACTION_ADDQ, 39 | INSTRUCTION_ACTION_ADD, 40 | INSTRUCTION_ACTION_EOR, 41 | INSTRUCTION_ACTION_TST, 42 | INSTRUCTION_ACTION_BCHG, 43 | INSTRUCTION_ACTION_BCLR, 44 | INSTRUCTION_ACTION_BSET, 45 | INSTRUCTION_ACTION_BTST, 46 | INSTRUCTION_ACTION_MOVEP, 47 | INSTRUCTION_ACTION_MOVEA, 48 | INSTRUCTION_ACTION_MOVE, 49 | INSTRUCTION_ACTION_LINK, 50 | INSTRUCTION_ACTION_UNLK, 51 | INSTRUCTION_ACTION_NEGX, 52 | INSTRUCTION_ACTION_CLR, 53 | INSTRUCTION_ACTION_NEG, 54 | INSTRUCTION_ACTION_NOT, 55 | INSTRUCTION_ACTION_EXT, 56 | INSTRUCTION_ACTION_NBCD, 57 | INSTRUCTION_ACTION_SWAP, 58 | INSTRUCTION_ACTION_PEA, 59 | INSTRUCTION_ACTION_ILLEGAL, 60 | INSTRUCTION_ACTION_TAS, 61 | INSTRUCTION_ACTION_TRAP, 62 | INSTRUCTION_ACTION_MOVE_USP, 63 | INSTRUCTION_ACTION_RESET, 64 | INSTRUCTION_ACTION_STOP, 65 | INSTRUCTION_ACTION_RTE, 66 | INSTRUCTION_ACTION_RTS, 67 | INSTRUCTION_ACTION_TRAPV, 68 | INSTRUCTION_ACTION_RTR, 69 | INSTRUCTION_ACTION_JSR, 70 | INSTRUCTION_ACTION_JMP, 71 | INSTRUCTION_ACTION_LEA, 72 | INSTRUCTION_ACTION_MOVEM, 73 | INSTRUCTION_ACTION_CHK, 74 | INSTRUCTION_ACTION_SCC, 75 | INSTRUCTION_ACTION_DBCC, 76 | INSTRUCTION_ACTION_BRA_SHORT, 77 | INSTRUCTION_ACTION_BRA_WORD, 78 | INSTRUCTION_ACTION_BSR_SHORT, 79 | INSTRUCTION_ACTION_BSR_WORD, 80 | INSTRUCTION_ACTION_BCC_SHORT, 81 | INSTRUCTION_ACTION_BCC_WORD, 82 | INSTRUCTION_ACTION_MOVEQ, 83 | INSTRUCTION_ACTION_DIVS, 84 | INSTRUCTION_ACTION_DIVU, 85 | INSTRUCTION_ACTION_SBCD, 86 | INSTRUCTION_ACTION_SUBX, 87 | INSTRUCTION_ACTION_MULS, 88 | INSTRUCTION_ACTION_MULU, 89 | INSTRUCTION_ACTION_ABCD, 90 | INSTRUCTION_ACTION_EXG, 91 | INSTRUCTION_ACTION_ADDX, 92 | INSTRUCTION_ACTION_ASD_MEMORY, 93 | INSTRUCTION_ACTION_ASD_REGISTER, 94 | INSTRUCTION_ACTION_LSD_MEMORY, 95 | INSTRUCTION_ACTION_LSD_REGISTER, 96 | INSTRUCTION_ACTION_ROD_MEMORY, 97 | INSTRUCTION_ACTION_ROD_REGISTER, 98 | INSTRUCTION_ACTION_ROXD_MEMORY, 99 | INSTRUCTION_ACTION_ROXD_REGISTER, 100 | INSTRUCTION_ACTION_UNIMPLEMENTED_1, 101 | INSTRUCTION_ACTION_UNIMPLEMENTED_2, 102 | INSTRUCTION_ACTION_NOP 103 | } InstructionAction; 104 | 105 | typedef enum InstructionSize 106 | { 107 | INSTRUCTION_SIZE_BYTE, 108 | INSTRUCTION_SIZE_WORD, 109 | INSTRUCTION_SIZE_LONGWORD, 110 | INSTRUCTION_SIZE_LONGWORD_REGISTER_BYTE_MEMORY, 111 | INSTRUCTION_SIZE_MOVE, 112 | INSTRUCTION_SIZE_EXT, 113 | INSTRUCTION_SIZE_STANDARD, 114 | INSTRUCTION_SIZE_NONE 115 | } InstructionSize; 116 | 117 | typedef enum InstructionSourceOperand 118 | { 119 | INSTRUCTION_SOURCE_IMMEDIATE_DATA, 120 | INSTRUCTION_SOURCE_DATA_REGISTER_SECONDARY, 121 | INSTRUCTION_SOURCE_IMMEDIATE_DATA_BYTE, 122 | INSTRUCTION_SOURCE_MEMORY_ADDRESS_PRIMARY, 123 | INSTRUCTION_SOURCE_STATUS_REGISTER, 124 | INSTRUCTION_SOURCE_IMMEDIATE_DATA_WORD, 125 | INSTRUCTION_SOURCE_BCD_X, 126 | INSTRUCTION_SOURCE_DATA_REGISTER_SECONDARY_OR_PRIMARY_ADDRESS_MODE, 127 | INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE_SIZED, 128 | INSTRUCTION_SOURCE_ADDRESS_REGISTER_PRIMARY_POSTINCREMENT, 129 | INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE, 130 | INSTRUCTION_SOURCE_PRIMARY_ADDRESS_MODE_WORD, 131 | INSTRUCTION_SOURCE_NONE 132 | } InstructionSourceOperand; 133 | 134 | typedef enum InstructionDestinationOperand 135 | { 136 | INSTRUCTION_DESTINATION_DATA_REGISTER_PRIMARY, 137 | INSTRUCTION_DESTINATION_DATA_REGISTER_SECONDARY, 138 | INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY, 139 | INSTRUCTION_DESTINATION_SECONDARY_ADDRESS_MODE, 140 | INSTRUCTION_DESTINATION_BCD_X, 141 | INSTRUCTION_DESTINATION_DATA_REGISTER_SECONDARY_OR_PRIMARY_ADDRESS_MODE, 142 | INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY_FULL, 143 | INSTRUCTION_DESTINATION_ADDRESS_REGISTER_SECONDARY_POSTINCREMENT, 144 | INSTRUCTION_DESTINATION_PRIMARY_ADDRESS_MODE, 145 | INSTRUCTION_DESTINATION_CONDITION_CODE_REGISTER, 146 | INSTRUCTION_DESTINATION_STATUS_REGISTER, 147 | INSTRUCTION_DESTINATION_MOVEM, 148 | INSTRUCTION_DESTINATION_MOVEP, 149 | INSTRUCTION_DESTINATION_NONE 150 | } InstructionDestinationOperand; 151 | 152 | typedef enum InstructionCarry 153 | { 154 | INSTRUCTION_CARRY_STANDARD_CARRY, 155 | INSTRUCTION_CARRY_STANDARD_BORROW, 156 | INSTRUCTION_CARRY_NEG, 157 | INSTRUCTION_CARRY_CLEAR, 158 | INSTRUCTION_CARRY_UNDEFINED, 159 | INSTRUCTION_CARRY_UNAFFECTED 160 | } InstructionCarry; 161 | 162 | typedef enum InstructionOverflow 163 | { 164 | INSTRUCTION_OVERFLOW_ADD, 165 | INSTRUCTION_OVERFLOW_SUB, 166 | INSTRUCTION_OVERFLOW_NEG, 167 | INSTRUCTION_OVERFLOW_CLEARED, 168 | INSTRUCTION_OVERFLOW_UNDEFINED, 169 | INSTRUCTION_OVERFLOW_UNAFFECTED 170 | } InstructionOverflow; 171 | 172 | typedef enum InstructionZero 173 | { 174 | INSTRUCTION_ZERO_CLEAR_IF_NONZERO_UNAFFECTED_OTHERWISE, 175 | INSTRUCTION_ZERO_SET_IF_ZERO_CLEAR_OTHERWISE, 176 | INSTRUCTION_ZERO_UNDEFINED, 177 | INSTRUCTION_ZERO_UNAFFECTED 178 | } InstructionZero; 179 | 180 | typedef enum InstructionNegative 181 | { 182 | INSTRUCTION_NEGATIVE_SET_IF_NEGATIVE_CLEAR_OTHERWISE, 183 | INSTRUCTION_NEGATIVE_UNAFFECTED 184 | } InstructionNegative; 185 | 186 | typedef enum InstructionExtend 187 | { 188 | INSTRUCTION_EXTEND_SET_TO_CARRY, 189 | INSTRUCTION_EXTEND_UNAFFECTED 190 | } InstructionExtend; 191 | 192 | InstructionAction Instruction_GetAction(const Instruction instruction); 193 | cc_bool Instruction_IsSourceOperandRead(const Instruction instruction); 194 | cc_bool Instruction_IsDestinationOperandRead(const Instruction instruction); 195 | cc_bool Instruction_IsDestinationOperandWritten(const Instruction instruction); 196 | InstructionSize Instruction_GetSize(const Instruction instruction); 197 | InstructionSourceOperand Instruction_GetSourceOperand(const Instruction instruction); 198 | InstructionDestinationOperand Instruction_GetDestinationOperand(const Instruction instruction); 199 | InstructionCarry Instruction_GetCarryModifier(const Instruction instruction); 200 | InstructionOverflow Instruction_GetOverflowModifier(const Instruction instruction); 201 | InstructionZero Instruction_GetZeroModifier(const Instruction instruction); 202 | InstructionNegative Instruction_GetNegativeModifier(const Instruction instruction); 203 | InstructionExtend Instruction_GetExtendModifier(const Instruction instruction); 204 | cc_bool Instruction_IsPrivileged(const Instruction instruction); 205 | 206 | #endif /* INCLUDE_GUARD_FB923D67_894A_4DE9_A848_05748F0BFEE7 */ 207 | -------------------------------------------------------------------------------- /interpreter/unity.c: -------------------------------------------------------------------------------- 1 | #include "clown68000.c" 2 | #include "../common/opcode.c" 3 | --------------------------------------------------------------------------------