├── .gitignore ├── .github └── workflows │ └── linting.yml ├── library.properties ├── LICENSE.md ├── examples └── count_by_twos │ └── count_by_twos.ino ├── src ├── CodesXCB.h ├── CodesED.h ├── Z80.h ├── CodesCB.h ├── Codes.h ├── CodesXX.h ├── Tables.h └── Z80.c └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /.github/workflows/linting.yml: -------------------------------------------------------------------------------- 1 | name: Lint Library 2 | on: [push, pull_request] 3 | jobs: 4 | lint: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - uses: arduino/arduino-lint-action@v1 9 | with: 10 | library-manager: update 11 | compliance: strict 12 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Z80 2 | version=1.0.2 3 | author=Jack Kingsman , Marat Fayzullin 4 | maintainer=Jack Kingsman 5 | sentence=A Z80 CPU implementation for the Arduino Mega. 6 | paragraph=Offers complete documented and undocumented emulation of the Z80 CPU, capable of executing machine code in stepwise or cycle-wise fashion. 7 | category=Other 8 | url=https://github.com/jkingsman/Z80Mega 9 | architectures=* 10 | includes=Z80.h 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Licensing 2 | 3 | As this is a collection of minor changes to Mr. Fayzullin's original work, it is released under [identical terms as his Z80 code](https://fms.komkon.org/EMUL8/): 4 | 5 | * You can use these resources for any non-profit purposes, as long as you make a proper reference to [Mr. Fayzullin]. 6 | * You cannot use any of these resources to gain profit. This includes using them in commercial projects, putting them onto companion CDs, etc. If you want to use my work in a commercial project, please, contact [Mr. Fayzullin] to negotiate the terms. 7 | * You cannot distribute these resources yourself, through your own WWW or FTP sites, even if they are non-profit. It is ok to have them as part of your non-profit software though. 8 | * If you use my code for your own project, please, let [Mr. Fayzullin] know about it. 9 | * The above license terms are incompatible with GPL. Thus, you should avoid making the source code from this page and any derived code part of a GPLed project. 10 | -------------------------------------------------------------------------------- /examples/count_by_twos/count_by_twos.ino: -------------------------------------------------------------------------------- 1 | #define MEM_SIZE 512 2 | #define STEP_DELAY 300 3 | 4 | #include 5 | 6 | /* 7 | * Global declaration of RAM. This demo program counts 8 | * up by 2s at memory address 0x0010. 9 | */ 10 | byte ram[MEM_SIZE] = { 11 | // count by 2s at 0x10 12 | 0x3E, 0x00, // LD A,$04 13 | 0x32, 0x10, 0x00, // LD ($0010),A 14 | 0x3A, 0x10, 0x00, // LD A,($0010) 15 | 0x3C, // INC A 16 | 0x3C, // INC A 17 | 0x32, 0x10, 0x00, // LD ($0010),A 18 | 0x18, 0xF6 // JR $5 19 | }; 20 | 21 | /* 22 | * Five mandatory functions! Compilation will fail if these are 23 | * not defined. You must implement them yourself. 24 | */ 25 | 26 | // Memory write -- write the Value to memory location Addr 27 | void WrZ80(register zword Addr, register byte Value) { 28 | ram[Addr] = Value; 29 | } 30 | 31 | // Memory read -- read the value at memory location Addr 32 | byte RdZ80(register zword Addr) { 33 | return ram[Addr]; 34 | } 35 | 36 | // IO -- output the Value on the Port (currently does nothing) 37 | // This is generally optional unless your code uses IO 38 | // Can be left blank. 39 | void OutZ80(register zword Port, register byte Value) {} 40 | 41 | // IO -- read a value from Port (currently defaults to 0) 42 | // This is generally optional unless your code uses IO 43 | // Can be left empty as long as it returns a byte. 44 | byte InZ80(register zword Port) { 45 | return 0; 46 | } 47 | 48 | // Advanced -- called when an emulator-specific opcode of 49 | // ED FE is encountered. Generally can be left empty. 50 | void PatchZ80(register Z80 *R) {} 51 | 52 | // create a CPU core object 53 | Z80 cpu; 54 | 55 | void setup() { 56 | Serial.begin(9600); 57 | 58 | // Reset the CPU to 0x00 and zero the regs/flags 59 | ResetZ80(&cpu); 60 | } 61 | 62 | void loop() { 63 | // print out current program counter 64 | // see Z80.h for the struct definition + fields 65 | Serial.print("PC: "); 66 | Serial.println(cpu.PC.W); 67 | 68 | // execute single opcode from memory at the current PC 69 | StepZ80(&cpu); 70 | 71 | // display the contents of memory where we're counting up (0x0010) 72 | Serial.print("Current value of 0x0010: "); 73 | Serial.println(RdZ80(0x0010)); 74 | 75 | // delay before stepping again so you can watch it count up slowly 76 | delay(STEP_DELAY); 77 | } 78 | -------------------------------------------------------------------------------- /src/CodesXCB.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** CodesXCB.h **/ 4 | /** **/ 5 | /** This file contains implementation for FD/DD-CB tables **/ 6 | /** of Z80 commands. It is included from Z80.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | case RLC_xHL: I=RdZ80(J.W);M_RLC(I);WrZ80(J.W,I);break; 15 | case RRC_xHL: I=RdZ80(J.W);M_RRC(I);WrZ80(J.W,I);break; 16 | case RL_xHL: I=RdZ80(J.W);M_RL(I);WrZ80(J.W,I);break; 17 | case RR_xHL: I=RdZ80(J.W);M_RR(I);WrZ80(J.W,I);break; 18 | case SLA_xHL: I=RdZ80(J.W);M_SLA(I);WrZ80(J.W,I);break; 19 | case SRA_xHL: I=RdZ80(J.W);M_SRA(I);WrZ80(J.W,I);break; 20 | case SLL_xHL: I=RdZ80(J.W);M_SLL(I);WrZ80(J.W,I);break; 21 | case SRL_xHL: I=RdZ80(J.W);M_SRL(I);WrZ80(J.W,I);break; 22 | 23 | case BIT0_B: case BIT0_C: case BIT0_D: case BIT0_E: 24 | case BIT0_H: case BIT0_L: case BIT0_A: 25 | case BIT0_xHL: I=RdZ80(J.W);M_BIT(0,I);break; 26 | case BIT1_B: case BIT1_C: case BIT1_D: case BIT1_E: 27 | case BIT1_H: case BIT1_L: case BIT1_A: 28 | case BIT1_xHL: I=RdZ80(J.W);M_BIT(1,I);break; 29 | case BIT2_B: case BIT2_C: case BIT2_D: case BIT2_E: 30 | case BIT2_H: case BIT2_L: case BIT2_A: 31 | case BIT2_xHL: I=RdZ80(J.W);M_BIT(2,I);break; 32 | case BIT3_B: case BIT3_C: case BIT3_D: case BIT3_E: 33 | case BIT3_H: case BIT3_L: case BIT3_A: 34 | case BIT3_xHL: I=RdZ80(J.W);M_BIT(3,I);break; 35 | case BIT4_B: case BIT4_C: case BIT4_D: case BIT4_E: 36 | case BIT4_H: case BIT4_L: case BIT4_A: 37 | case BIT4_xHL: I=RdZ80(J.W);M_BIT(4,I);break; 38 | case BIT5_B: case BIT5_C: case BIT5_D: case BIT5_E: 39 | case BIT5_H: case BIT5_L: case BIT5_A: 40 | case BIT5_xHL: I=RdZ80(J.W);M_BIT(5,I);break; 41 | case BIT6_B: case BIT6_C: case BIT6_D: case BIT6_E: 42 | case BIT6_H: case BIT6_L: case BIT6_A: 43 | case BIT6_xHL: I=RdZ80(J.W);M_BIT(6,I);break; 44 | case BIT7_B: case BIT7_C: case BIT7_D: case BIT7_E: 45 | case BIT7_H: case BIT7_L: case BIT7_A: 46 | case BIT7_xHL: I=RdZ80(J.W);M_BIT(7,I);break; 47 | 48 | case RES0_xHL: I=RdZ80(J.W);M_RES(0,I);WrZ80(J.W,I);break; 49 | case RES1_xHL: I=RdZ80(J.W);M_RES(1,I);WrZ80(J.W,I);break; 50 | case RES2_xHL: I=RdZ80(J.W);M_RES(2,I);WrZ80(J.W,I);break; 51 | case RES3_xHL: I=RdZ80(J.W);M_RES(3,I);WrZ80(J.W,I);break; 52 | case RES4_xHL: I=RdZ80(J.W);M_RES(4,I);WrZ80(J.W,I);break; 53 | case RES5_xHL: I=RdZ80(J.W);M_RES(5,I);WrZ80(J.W,I);break; 54 | case RES6_xHL: I=RdZ80(J.W);M_RES(6,I);WrZ80(J.W,I);break; 55 | case RES7_xHL: I=RdZ80(J.W);M_RES(7,I);WrZ80(J.W,I);break; 56 | 57 | case SET0_xHL: I=RdZ80(J.W);M_SET(0,I);WrZ80(J.W,I);break; 58 | case SET1_xHL: I=RdZ80(J.W);M_SET(1,I);WrZ80(J.W,I);break; 59 | case SET2_xHL: I=RdZ80(J.W);M_SET(2,I);WrZ80(J.W,I);break; 60 | case SET3_xHL: I=RdZ80(J.W);M_SET(3,I);WrZ80(J.W,I);break; 61 | case SET4_xHL: I=RdZ80(J.W);M_SET(4,I);WrZ80(J.W,I);break; 62 | case SET5_xHL: I=RdZ80(J.W);M_SET(5,I);WrZ80(J.W,I);break; 63 | case SET6_xHL: I=RdZ80(J.W);M_SET(6,I);WrZ80(J.W,I);break; 64 | case SET7_xHL: I=RdZ80(J.W);M_SET(7,I);WrZ80(J.W,I);break; 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Z80 Core for Arduino Mega 2 | 3 | **This library only functions with the Arduino Mega or Mega 2560 due to memory constraints!** 4 | 5 | This is a free, open source project which comprises light modification of Marat Fayzullin's brilliant Z80 emulator in C in order to make it compatible with the Arduino Mega (other Arduinos do not have the memory to run it). You can view his [download page for the original code here](https://fms.komkon.org/EMUL8/). This library is based off of [`Z80-081707.zip`](https://fms.komkon.org/EMUL8/Z80-081707.zip). 6 | 7 | Reading over `Z80.h` is strongly encouraged to get a feel for the bitfields and core CPU structs, as well as the functions you must implement (see *Usage* below) and optional ones you can enable with by `#define`ing flags (such as running until `HALT` or running n cycles at a time as opposed to one opcode at a time, which is the default behavior). 8 | 9 | *THIS IS FIRST AND FOREMOST MARAT FAYZULLIN'S CODE AND HARD WORK. ALL I'VE DONE IS MAKE MINOR COMPATIBILITY AND CONVENIENCE MODIFICATIONS. USAGE IS SUBJECT TO HIS LICENSE TERMS ALONE.* 10 | 11 | The changes comprise: 12 | 13 | * Renaming the `SP` field in the state struct to `SPtr` because `SP` is a reserved keyword on AVR systems 14 | * Renaming the defined `word` type to `zword` since word with the Arduino type of the same name 15 | * Define `LSB_FIRST` to get existing Z80 sources working correctly 16 | * Define `RUNZ80` and `STEPZ80` flags in order to disable the `RunZ80` inclusion and instead include `StepZ80` 17 | * Define an additional function `StepZ80` which allows one to execute one opcode at a time, a feature I found in older versions of the emulator and loved but that was apparently removed in newer versions 18 | 19 | # Usage 20 | 21 | In order to compile this library, you need to implement five functions in your main `.ino` file: 22 | 23 | ```C 24 | // This is not mandatory in and of itself but is used in the below examples 25 | // and defines 128 bytes of memory to be read and written to 26 | byte ram[128]; 27 | 28 | // Memory write -- write the Value to memory location Addr 29 | void WrZ80(register zword Addr, register byte Value) { 30 | ram[Addr] = Value; 31 | } 32 | 33 | // Memory read -- read the value at memory location Addr 34 | byte RdZ80(register zword Addr) { 35 | return ram[Addr]; 36 | } 37 | 38 | // IO -- output the Value on the given IO Port 39 | // This is generally optional to have functional unless your code uses IO 40 | void OutZ80(register zword Port, register byte Value) {} 41 | 42 | // IO -- read a value from an IO Port (currently defaults to 0) 43 | // This is generally optional to have functional unless your code uses IO 44 | // The only requirement is that is must return a byte (0, in this case) 45 | byte InZ80(register zword Port) { 46 | return 0; 47 | } 48 | 49 | // Advanced -- called when an emulator-specific opcode of 50 | // ED FE is encountered. Generally can be left empty. 51 | void PatchZ80(register Z80 *R) {} 52 | ``` 53 | 54 | *Without these functions implemented, you will recieve compilation errors.* 55 | 56 | # Example 57 | 58 | Below is a basic example program which runs a small program to count up by twos at `0x0010` and print the program counter and contents of `0x0010` as it goes. 59 | 60 | ```C 61 | #define MEM_SIZE 512 62 | #define STEP_DELAY 300 63 | 64 | #include 65 | 66 | /* 67 | * Global declaration of RAM. This demo program counts 68 | * up by 2s at memory address 0x0010. 69 | */ 70 | byte ram[MEM_SIZE] = { 71 | // count by 2s at 0x10 72 | 0x3E, 0x00, // LD A,$04 73 | 0x32, 0x10, 0x00, // LD ($0010),A 74 | 0x3A, 0x10, 0x00, // LD A,($0010) 75 | 0x3C, // INC A 76 | 0x3C, // INC A 77 | 0x32, 0x10, 0x00, // LD ($0010),A 78 | 0x18, 0xF6 // JR $5 79 | }; 80 | 81 | // Memory write -- write the Value to memory location Addr 82 | void WrZ80(register zword Addr, register byte Value) { 83 | ram[Addr] = Value; 84 | } 85 | 86 | // Memory read -- read the value at memory location Addr 87 | byte RdZ80(register zword Addr) { 88 | return ram[Addr]; 89 | } 90 | 91 | // IO -- output the Value on the Port (currently does nothing) 92 | void OutZ80(register zword Port, register byte Value) {} 93 | 94 | // IO -- read a value from Port (currently defaults to 0) 95 | byte InZ80(register zword Port) { 96 | return 0; 97 | } 98 | 99 | // Advanced -- called when an emulator-specific opcode of 100 | // ED FE is encountered. Generally can be left empty. 101 | void PatchZ80(register Z80 *R) {} 102 | 103 | // create a CPU core object 104 | Z80 cpu; 105 | 106 | void setup() { 107 | Serial.begin(9600); 108 | 109 | // Reset the CPU to 0x00 and zero the regs/flags 110 | ResetZ80(&cpu); 111 | } 112 | 113 | void loop() { 114 | // print out current program counter 115 | // see Z80.h for the struct definition + fields 116 | Serial.print("PC: "); 117 | Serial.println(cpu.PC.W); 118 | 119 | // execute single opcode from memory at the current PC 120 | StepZ80(&cpu); 121 | 122 | // display the contents of memory where we're counting up (0x0010) 123 | Serial.print("Current value of 0x0010: "); 124 | Serial.println(RdZ80(0x0010)); 125 | 126 | // delay before stepping again so you can watch it count up slowly 127 | delay(STEP_DELAY); 128 | } 129 | ``` 130 | -------------------------------------------------------------------------------- /src/CodesED.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** CodesED.h **/ 4 | /** **/ 5 | /** This file contains implementation for the ED table of **/ 6 | /** Z80 commands. It is included from Z80.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | /** This is a special patch for emulating BIOS calls: ********/ 15 | case DB_FE: PatchZ80(R);break; 16 | /*************************************************************/ 17 | 18 | case ADC_HL_BC: M_ADCW(BC);break; 19 | case ADC_HL_DE: M_ADCW(DE);break; 20 | case ADC_HL_HL: M_ADCW(HL);break; 21 | case ADC_HL_SP: M_ADCW(SPtr);break; 22 | 23 | case SBC_HL_BC: M_SBCW(BC);break; 24 | case SBC_HL_DE: M_SBCW(DE);break; 25 | case SBC_HL_HL: M_SBCW(HL);break; 26 | case SBC_HL_SP: M_SBCW(SPtr);break; 27 | 28 | case LD_xWORDe_HL: 29 | J.B.l=OpZ80(R->PC.W++); 30 | J.B.h=OpZ80(R->PC.W++); 31 | WrZ80(J.W++,R->HL.B.l); 32 | WrZ80(J.W,R->HL.B.h); 33 | break; 34 | case LD_xWORDe_DE: 35 | J.B.l=OpZ80(R->PC.W++); 36 | J.B.h=OpZ80(R->PC.W++); 37 | WrZ80(J.W++,R->DE.B.l); 38 | WrZ80(J.W,R->DE.B.h); 39 | break; 40 | case LD_xWORDe_BC: 41 | J.B.l=OpZ80(R->PC.W++); 42 | J.B.h=OpZ80(R->PC.W++); 43 | WrZ80(J.W++,R->BC.B.l); 44 | WrZ80(J.W,R->BC.B.h); 45 | break; 46 | case LD_xWORDe_SP: 47 | J.B.l=OpZ80(R->PC.W++); 48 | J.B.h=OpZ80(R->PC.W++); 49 | WrZ80(J.W++,R->SPtr.B.l); 50 | WrZ80(J.W,R->SPtr.B.h); 51 | break; 52 | 53 | case LD_HL_xWORDe: 54 | J.B.l=OpZ80(R->PC.W++); 55 | J.B.h=OpZ80(R->PC.W++); 56 | R->HL.B.l=RdZ80(J.W++); 57 | R->HL.B.h=RdZ80(J.W); 58 | break; 59 | case LD_DE_xWORDe: 60 | J.B.l=OpZ80(R->PC.W++); 61 | J.B.h=OpZ80(R->PC.W++); 62 | R->DE.B.l=RdZ80(J.W++); 63 | R->DE.B.h=RdZ80(J.W); 64 | break; 65 | case LD_BC_xWORDe: 66 | J.B.l=OpZ80(R->PC.W++); 67 | J.B.h=OpZ80(R->PC.W++); 68 | R->BC.B.l=RdZ80(J.W++); 69 | R->BC.B.h=RdZ80(J.W); 70 | break; 71 | case LD_SP_xWORDe: 72 | J.B.l=OpZ80(R->PC.W++); 73 | J.B.h=OpZ80(R->PC.W++); 74 | R->SPtr.B.l=RdZ80(J.W++); 75 | R->SPtr.B.h=RdZ80(J.W); 76 | break; 77 | 78 | case RRD: 79 | I=RdZ80(R->HL.W); 80 | J.B.l=(I>>4)|(R->AF.B.h<<4); 81 | WrZ80(R->HL.W,J.B.l); 82 | R->AF.B.h=(I&0x0F)|(R->AF.B.h&0xF0); 83 | R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG); 84 | break; 85 | case RLD: 86 | I=RdZ80(R->HL.W); 87 | J.B.l=(I<<4)|(R->AF.B.h&0x0F); 88 | WrZ80(R->HL.W,J.B.l); 89 | R->AF.B.h=(I>>4)|(R->AF.B.h&0xF0); 90 | R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG); 91 | break; 92 | 93 | case LD_A_I: 94 | R->AF.B.h=R->I; 95 | R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h]; 96 | break; 97 | 98 | case LD_A_R: 99 | R->R++; 100 | R->AF.B.h=(byte)(R->R-R->ICount); 101 | R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h]; 102 | break; 103 | 104 | case LD_I_A: R->I=R->AF.B.h;break; 105 | case LD_R_A: break; 106 | 107 | case IM_0: R->IFF&=~(IFF_IM1|IFF_IM2);break; 108 | case IM_1: R->IFF=(R->IFF&~IFF_IM2)|IFF_IM1;break; 109 | case IM_2: R->IFF=(R->IFF&~IFF_IM1)|IFF_IM2;break; 110 | 111 | case RETI: 112 | case RETN: if(R->IFF&IFF_2) R->IFF|=IFF_1; else R->IFF&=~IFF_1; 113 | M_RET;break; 114 | 115 | case NEG: I=R->AF.B.h;R->AF.B.h=0;M_SUB(I);break; 116 | 117 | case IN_B_xC: M_IN(R->BC.B.h);break; 118 | case IN_C_xC: M_IN(R->BC.B.l);break; 119 | case IN_D_xC: M_IN(R->DE.B.h);break; 120 | case IN_E_xC: M_IN(R->DE.B.l);break; 121 | case IN_H_xC: M_IN(R->HL.B.h);break; 122 | case IN_L_xC: M_IN(R->HL.B.l);break; 123 | case IN_A_xC: M_IN(R->AF.B.h);break; 124 | case IN_F_xC: M_IN(J.B.l);break; 125 | 126 | case OUT_xC_B: OutZ80(R->BC.W,R->BC.B.h);break; 127 | case OUT_xC_C: OutZ80(R->BC.W,R->BC.B.l);break; 128 | case OUT_xC_D: OutZ80(R->BC.W,R->DE.B.h);break; 129 | case OUT_xC_E: OutZ80(R->BC.W,R->DE.B.l);break; 130 | case OUT_xC_H: OutZ80(R->BC.W,R->HL.B.h);break; 131 | case OUT_xC_L: OutZ80(R->BC.W,R->HL.B.l);break; 132 | case OUT_xC_A: OutZ80(R->BC.W,R->AF.B.h);break; 133 | 134 | case INI: 135 | WrZ80(R->HL.W++,InZ80(R->BC.W)); 136 | --R->BC.B.h; 137 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG); 138 | break; 139 | 140 | case INIR: 141 | do 142 | { 143 | WrZ80(R->HL.W++,InZ80(R->BC.W)); 144 | --R->BC.B.h;R->ICount-=21; 145 | } 146 | while(R->BC.B.h&&(R->ICount>0)); 147 | if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; } 148 | else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; } 149 | break; 150 | 151 | case IND: 152 | WrZ80(R->HL.W--,InZ80(R->BC.W)); 153 | --R->BC.B.h; 154 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG); 155 | break; 156 | 157 | case INDR: 158 | do 159 | { 160 | WrZ80(R->HL.W--,InZ80(R->BC.W)); 161 | --R->BC.B.h;R->ICount-=21; 162 | } 163 | while(R->BC.B.h&&(R->ICount>0)); 164 | if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; } 165 | else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; } 166 | break; 167 | 168 | case OUTI: 169 | --R->BC.B.h; 170 | I=RdZ80(R->HL.W++); 171 | OutZ80(R->BC.W,I); 172 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 173 | break; 174 | 175 | case OTIR: 176 | do 177 | { 178 | --R->BC.B.h; 179 | I=RdZ80(R->HL.W++); 180 | OutZ80(R->BC.W,I); 181 | R->ICount-=21; 182 | } 183 | while(R->BC.B.h&&(R->ICount>0)); 184 | if(R->BC.B.h) 185 | { 186 | R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 187 | R->PC.W-=2; 188 | } 189 | else 190 | { 191 | R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 192 | R->ICount+=5; 193 | } 194 | break; 195 | 196 | case OUTD: 197 | --R->BC.B.h; 198 | I=RdZ80(R->HL.W--); 199 | OutZ80(R->BC.W,I); 200 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 201 | break; 202 | 203 | case OTDR: 204 | do 205 | { 206 | --R->BC.B.h; 207 | I=RdZ80(R->HL.W--); 208 | OutZ80(R->BC.W,I); 209 | R->ICount-=21; 210 | } 211 | while(R->BC.B.h&&(R->ICount>0)); 212 | if(R->BC.B.h) 213 | { 214 | R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 215 | R->PC.W-=2; 216 | } 217 | else 218 | { 219 | R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 220 | R->ICount+=5; 221 | } 222 | break; 223 | 224 | case LDI: 225 | WrZ80(R->DE.W++,RdZ80(R->HL.W++)); 226 | --R->BC.W; 227 | R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0); 228 | break; 229 | 230 | case LDIR: 231 | do 232 | { 233 | WrZ80(R->DE.W++,RdZ80(R->HL.W++)); 234 | --R->BC.W;R->ICount-=21; 235 | } 236 | while(R->BC.W&&(R->ICount>0)); 237 | R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG); 238 | if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; } 239 | else R->ICount+=5; 240 | break; 241 | 242 | case LDD: 243 | WrZ80(R->DE.W--,RdZ80(R->HL.W--)); 244 | --R->BC.W; 245 | R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0); 246 | break; 247 | 248 | case LDDR: 249 | do 250 | { 251 | WrZ80(R->DE.W--,RdZ80(R->HL.W--)); 252 | --R->BC.W;R->ICount-=21; 253 | } 254 | while(R->BC.W&&(R->ICount>0)); 255 | R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG); 256 | if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; } 257 | else R->ICount+=5; 258 | break; 259 | 260 | case CPI: 261 | I=RdZ80(R->HL.W++); 262 | J.B.l=R->AF.B.h-I; 263 | --R->BC.W; 264 | R->AF.B.l = 265 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 266 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 267 | break; 268 | 269 | case CPIR: 270 | do 271 | { 272 | I=RdZ80(R->HL.W++); 273 | J.B.l=R->AF.B.h-I; 274 | --R->BC.W;R->ICount-=21; 275 | } 276 | while(R->BC.W&&J.B.l&&(R->ICount>0)); 277 | R->AF.B.l = 278 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 279 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 280 | if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5; 281 | break; 282 | 283 | case CPD: 284 | I=RdZ80(R->HL.W--); 285 | J.B.l=R->AF.B.h-I; 286 | --R->BC.W; 287 | R->AF.B.l = 288 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 289 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 290 | break; 291 | 292 | case CPDR: 293 | do 294 | { 295 | I=RdZ80(R->HL.W--); 296 | J.B.l=R->AF.B.h-I; 297 | --R->BC.W;R->ICount-=21; 298 | } 299 | while(R->BC.W&&J.B.l); 300 | R->AF.B.l = 301 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 302 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 303 | if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5; 304 | break; 305 | -------------------------------------------------------------------------------- /src/Z80.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** Z80.h **/ 4 | /** **/ 5 | /** This file contains declarations relevant to emulation **/ 6 | /** of Z80 CPU. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef Z80_H 14 | #define Z80_H 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /* Compilation options: */ 21 | /* #define DEBUG */ /* Compile debugging version */ 22 | #define LSB_FIRST /* Compile for low-endian CPU */ 23 | /* #define MSB_FIRST */ /* Compile for hi-endian CPU */ 24 | #define STEPZ80 /* Enable the stepz80 function*/ 25 | #define EXECZ80 /* Enable the execz80 function*/ 26 | 27 | /* LoopZ80() may return: */ 28 | #define INT_RST00 0x00C7 /* RST 00h */ 29 | #define INT_RST08 0x00CF /* RST 08h */ 30 | #define INT_RST10 0x00D7 /* RST 10h */ 31 | #define INT_RST18 0x00DF /* RST 18h */ 32 | #define INT_RST20 0x00E7 /* RST 20h */ 33 | #define INT_RST28 0x00EF /* RST 28h */ 34 | #define INT_RST30 0x00F7 /* RST 30h */ 35 | #define INT_RST38 0x00FF /* RST 38h */ 36 | #define INT_IRQ INT_RST38 /* Default IRQ opcode is FFh */ 37 | #define INT_NMI 0xFFFD /* Non-maskable interrupt */ 38 | #define INT_NONE 0xFFFF /* No interrupt required */ 39 | #define INT_QUIT 0xFFFE /* Exit the emulation */ 40 | 41 | /* Bits in Z80 F register: */ 42 | #define S_FLAG 0x80 /* 1: Result negative */ 43 | #define Z_FLAG 0x40 /* 1: Result is zero */ 44 | #define H_FLAG 0x10 /* 1: Halfcarry/Halfborrow */ 45 | #define P_FLAG 0x04 /* 1: Result is even */ 46 | #define V_FLAG 0x04 /* 1: Overflow occured */ 47 | #define N_FLAG 0x02 /* 1: Subtraction occured */ 48 | #define C_FLAG 0x01 /* 1: Carry/Borrow occured */ 49 | 50 | /* Bits in IFF flip-flops: */ 51 | #define IFF_1 0x01 /* IFF1 flip-flop */ 52 | #define IFF_IM1 0x02 /* 1: IM1 mode */ 53 | #define IFF_IM2 0x04 /* 1: IM2 mode */ 54 | #define IFF_2 0x08 /* IFF2 flip-flop */ 55 | #define IFF_EI 0x20 /* 1: EI pending */ 56 | #define IFF_HALT 0x80 /* 1: CPU HALTed */ 57 | 58 | /** Simple Datatypes *****************************************/ 59 | /** NOTICE: sizeof(byte)=1 and sizeof(zword)=2 **/ 60 | /*************************************************************/ 61 | #ifndef BYTE_TYPE_DEFINED 62 | #define BYTE_TYPE_DEFINED 63 | typedef unsigned char byte; 64 | #endif 65 | #ifndef WORD_TYPE_DEFINED 66 | #define WORD_TYPE_DEFINED 67 | typedef unsigned short zword; 68 | #endif 69 | typedef signed char offset; 70 | 71 | /** Structured Datatypes *************************************/ 72 | /** NOTICE: #define LSB_FIRST for machines where least **/ 73 | /** signifcant byte goes first. **/ 74 | /*************************************************************/ 75 | typedef union 76 | { 77 | #ifdef LSB_FIRST 78 | struct { byte l,h; } B; 79 | #else 80 | struct { byte h,l; } B; 81 | #endif 82 | zword W; 83 | } pair; 84 | 85 | typedef struct 86 | { 87 | pair AF,BC,DE,HL,IX,IY,PC,SPtr; /* Main registers */ 88 | pair AF1,BC1,DE1,HL1; /* Shadow registers */ 89 | byte IFF,I; /* Interrupt registers */ 90 | byte R; /* Refresh register */ 91 | 92 | int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */ 93 | /* between calls to LoopZ80() */ 94 | int IBackup; /* Private, don't touch */ 95 | zword IRequest; /* Set to address of pending IRQ */ 96 | byte IAutoReset; /* Set to 1 to autom. reset IRequest */ 97 | byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */ 98 | zword Trap; /* Set Trap to address to trace from */ 99 | byte Trace; /* Set Trace=1 to start tracing */ 100 | void *User; /* Arbitrary user data (ID,RAM*,etc.) */ 101 | } Z80; 102 | 103 | /** ResetZ80() ***********************************************/ 104 | /** This function can be used to reset the registers before **/ 105 | /** starting execution with RunZ80(). It sets registers to **/ 106 | /** their initial values. **/ 107 | /*************************************************************/ 108 | void ResetZ80(register Z80 *R); 109 | 110 | /** ExecZ80() ************************************************/ 111 | /** This function will execute given number of Z80 cycles. **/ 112 | /** It will then return the number of cycles left, possibly **/ 113 | /** negative, and current register values in R. **/ 114 | /*************************************************************/ 115 | #ifdef EXECZ80 116 | int ExecZ80(register Z80 *R,register int RunCycles); 117 | #endif 118 | 119 | /** IntZ80() *************************************************/ 120 | /** This function will generate interrupt of given vector. **/ 121 | /*************************************************************/ 122 | void IntZ80(register Z80 *R,register zword Vector); 123 | 124 | /** RunZ80() *************************************************/ 125 | /** This function will run Z80 code until an LoopZ80() call **/ 126 | /** returns INT_QUIT. It will return the PC at which **/ 127 | /** emulation stopped, and current register values in R. **/ 128 | /*************************************************************/ 129 | #ifdef RUNZ80 130 | zword RunZ80(register Z80 *R); 131 | #endif 132 | 133 | /** StepZ80() ************************************************/ 134 | /** This function will execute a single Z80 opcode. **/ 135 | /** It will return the current register values in R. **/ 136 | /*************************************************************/ 137 | #ifdef STEPZ80 138 | void StepZ80(register Z80 *R); 139 | #endif 140 | 141 | /** RdZ80()/WrZ80() ******************************************/ 142 | /** These functions are called when access to RAM occurs. **/ 143 | /** They allow to control memory access. **/ 144 | /************************************ TO BE WRITTEN BY USER **/ 145 | void WrZ80(register zword Addr,register byte Value); 146 | byte RdZ80(register zword Addr); 147 | 148 | /** InZ80()/OutZ80() *****************************************/ 149 | /** Z80 emulation calls these functions to read/write from **/ 150 | /** I/O ports. There can be 65536 I/O ports, but only first **/ 151 | /** 256 are usually used. **/ 152 | /************************************ TO BE WRITTEN BY USER **/ 153 | void OutZ80(register zword Port,register byte Value); 154 | byte InZ80(register zword Port); 155 | 156 | /** PatchZ80() ***********************************************/ 157 | /** Z80 emulation calls this function when it encounters a **/ 158 | /** special patch command (ED FE) provided for user needs. **/ 159 | /** For example, it can be called to emulate BIOS calls, **/ 160 | /** such as disk and tape access. Replace it with an empty **/ 161 | /** macro for no patching. **/ 162 | /************************************ TO BE WRITTEN BY USER **/ 163 | void PatchZ80(register Z80 *R); 164 | 165 | /** DebugZ80() ***********************************************/ 166 | /** This function should exist if DEBUG is #defined. When **/ 167 | /** Trace!=0, it is called after each command executed by **/ 168 | /** the CPU, and given the Z80 registers. Emulation exits **/ 169 | /** if DebugZ80() returns 0. **/ 170 | /*************************************************************/ 171 | #ifdef DEBUG 172 | byte DebugZ80(register Z80 *R); 173 | #endif 174 | 175 | /** LoopZ80() ************************************************/ 176 | /** Z80 emulation calls this function periodically to check **/ 177 | /** if the system hardware requires any interrupts. This **/ 178 | /** function must return an address of the interrupt vector **/ 179 | /** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt. **/ 180 | /** Return INT_QUIT to exit the emulation loop. **/ 181 | /************************************ TO BE WRITTEN BY USER **/ 182 | zword LoopZ80(register Z80 *R); 183 | 184 | /** JumpZ80() ************************************************/ 185 | /** Z80 emulation calls this function when it executes a **/ 186 | /** JP, JR, CALL, RST, or RET. You can use JumpZ80() to **/ 187 | /** trap these opcodes and switch memory layout. **/ 188 | /************************************ TO BE WRITTEN BY USER **/ 189 | #ifndef JUMPZ80 190 | #define JumpZ80(PC) 191 | #else 192 | void JumpZ80(zword PC); 193 | #endif 194 | 195 | #ifdef __cplusplus 196 | } 197 | #endif 198 | #endif /* Z80_H */ 199 | -------------------------------------------------------------------------------- /src/CodesCB.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** CodesCB.h **/ 4 | /** **/ 5 | /** This file contains implementation for the CB table of **/ 6 | /** Z80 commands. It is included from Z80.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | case RLC_B: M_RLC(R->BC.B.h);break; case RLC_C: M_RLC(R->BC.B.l);break; 15 | case RLC_D: M_RLC(R->DE.B.h);break; case RLC_E: M_RLC(R->DE.B.l);break; 16 | case RLC_H: M_RLC(R->HL.B.h);break; case RLC_L: M_RLC(R->HL.B.l);break; 17 | case RLC_xHL: I=RdZ80(R->HL.W);M_RLC(I);WrZ80(R->HL.W,I);break; 18 | case RLC_A: M_RLC(R->AF.B.h);break; 19 | 20 | case RRC_B: M_RRC(R->BC.B.h);break; case RRC_C: M_RRC(R->BC.B.l);break; 21 | case RRC_D: M_RRC(R->DE.B.h);break; case RRC_E: M_RRC(R->DE.B.l);break; 22 | case RRC_H: M_RRC(R->HL.B.h);break; case RRC_L: M_RRC(R->HL.B.l);break; 23 | case RRC_xHL: I=RdZ80(R->HL.W);M_RRC(I);WrZ80(R->HL.W,I);break; 24 | case RRC_A: M_RRC(R->AF.B.h);break; 25 | 26 | case RL_B: M_RL(R->BC.B.h);break; case RL_C: M_RL(R->BC.B.l);break; 27 | case RL_D: M_RL(R->DE.B.h);break; case RL_E: M_RL(R->DE.B.l);break; 28 | case RL_H: M_RL(R->HL.B.h);break; case RL_L: M_RL(R->HL.B.l);break; 29 | case RL_xHL: I=RdZ80(R->HL.W);M_RL(I);WrZ80(R->HL.W,I);break; 30 | case RL_A: M_RL(R->AF.B.h);break; 31 | 32 | case RR_B: M_RR(R->BC.B.h);break; case RR_C: M_RR(R->BC.B.l);break; 33 | case RR_D: M_RR(R->DE.B.h);break; case RR_E: M_RR(R->DE.B.l);break; 34 | case RR_H: M_RR(R->HL.B.h);break; case RR_L: M_RR(R->HL.B.l);break; 35 | case RR_xHL: I=RdZ80(R->HL.W);M_RR(I);WrZ80(R->HL.W,I);break; 36 | case RR_A: M_RR(R->AF.B.h);break; 37 | 38 | case SLA_B: M_SLA(R->BC.B.h);break; case SLA_C: M_SLA(R->BC.B.l);break; 39 | case SLA_D: M_SLA(R->DE.B.h);break; case SLA_E: M_SLA(R->DE.B.l);break; 40 | case SLA_H: M_SLA(R->HL.B.h);break; case SLA_L: M_SLA(R->HL.B.l);break; 41 | case SLA_xHL: I=RdZ80(R->HL.W);M_SLA(I);WrZ80(R->HL.W,I);break; 42 | case SLA_A: M_SLA(R->AF.B.h);break; 43 | 44 | case SRA_B: M_SRA(R->BC.B.h);break; case SRA_C: M_SRA(R->BC.B.l);break; 45 | case SRA_D: M_SRA(R->DE.B.h);break; case SRA_E: M_SRA(R->DE.B.l);break; 46 | case SRA_H: M_SRA(R->HL.B.h);break; case SRA_L: M_SRA(R->HL.B.l);break; 47 | case SRA_xHL: I=RdZ80(R->HL.W);M_SRA(I);WrZ80(R->HL.W,I);break; 48 | case SRA_A: M_SRA(R->AF.B.h);break; 49 | 50 | case SLL_B: M_SLL(R->BC.B.h);break; case SLL_C: M_SLL(R->BC.B.l);break; 51 | case SLL_D: M_SLL(R->DE.B.h);break; case SLL_E: M_SLL(R->DE.B.l);break; 52 | case SLL_H: M_SLL(R->HL.B.h);break; case SLL_L: M_SLL(R->HL.B.l);break; 53 | case SLL_xHL: I=RdZ80(R->HL.W);M_SLL(I);WrZ80(R->HL.W,I);break; 54 | case SLL_A: M_SLL(R->AF.B.h);break; 55 | 56 | case SRL_B: M_SRL(R->BC.B.h);break; case SRL_C: M_SRL(R->BC.B.l);break; 57 | case SRL_D: M_SRL(R->DE.B.h);break; case SRL_E: M_SRL(R->DE.B.l);break; 58 | case SRL_H: M_SRL(R->HL.B.h);break; case SRL_L: M_SRL(R->HL.B.l);break; 59 | case SRL_xHL: I=RdZ80(R->HL.W);M_SRL(I);WrZ80(R->HL.W,I);break; 60 | case SRL_A: M_SRL(R->AF.B.h);break; 61 | 62 | case BIT0_B: M_BIT(0,R->BC.B.h);break; case BIT0_C: M_BIT(0,R->BC.B.l);break; 63 | case BIT0_D: M_BIT(0,R->DE.B.h);break; case BIT0_E: M_BIT(0,R->DE.B.l);break; 64 | case BIT0_H: M_BIT(0,R->HL.B.h);break; case BIT0_L: M_BIT(0,R->HL.B.l);break; 65 | case BIT0_xHL: I=RdZ80(R->HL.W);M_BIT(0,I);break; 66 | case BIT0_A: M_BIT(0,R->AF.B.h);break; 67 | 68 | case BIT1_B: M_BIT(1,R->BC.B.h);break; case BIT1_C: M_BIT(1,R->BC.B.l);break; 69 | case BIT1_D: M_BIT(1,R->DE.B.h);break; case BIT1_E: M_BIT(1,R->DE.B.l);break; 70 | case BIT1_H: M_BIT(1,R->HL.B.h);break; case BIT1_L: M_BIT(1,R->HL.B.l);break; 71 | case BIT1_xHL: I=RdZ80(R->HL.W);M_BIT(1,I);break; 72 | case BIT1_A: M_BIT(1,R->AF.B.h);break; 73 | 74 | case BIT2_B: M_BIT(2,R->BC.B.h);break; case BIT2_C: M_BIT(2,R->BC.B.l);break; 75 | case BIT2_D: M_BIT(2,R->DE.B.h);break; case BIT2_E: M_BIT(2,R->DE.B.l);break; 76 | case BIT2_H: M_BIT(2,R->HL.B.h);break; case BIT2_L: M_BIT(2,R->HL.B.l);break; 77 | case BIT2_xHL: I=RdZ80(R->HL.W);M_BIT(2,I);break; 78 | case BIT2_A: M_BIT(2,R->AF.B.h);break; 79 | 80 | case BIT3_B: M_BIT(3,R->BC.B.h);break; case BIT3_C: M_BIT(3,R->BC.B.l);break; 81 | case BIT3_D: M_BIT(3,R->DE.B.h);break; case BIT3_E: M_BIT(3,R->DE.B.l);break; 82 | case BIT3_H: M_BIT(3,R->HL.B.h);break; case BIT3_L: M_BIT(3,R->HL.B.l);break; 83 | case BIT3_xHL: I=RdZ80(R->HL.W);M_BIT(3,I);break; 84 | case BIT3_A: M_BIT(3,R->AF.B.h);break; 85 | 86 | case BIT4_B: M_BIT(4,R->BC.B.h);break; case BIT4_C: M_BIT(4,R->BC.B.l);break; 87 | case BIT4_D: M_BIT(4,R->DE.B.h);break; case BIT4_E: M_BIT(4,R->DE.B.l);break; 88 | case BIT4_H: M_BIT(4,R->HL.B.h);break; case BIT4_L: M_BIT(4,R->HL.B.l);break; 89 | case BIT4_xHL: I=RdZ80(R->HL.W);M_BIT(4,I);break; 90 | case BIT4_A: M_BIT(4,R->AF.B.h);break; 91 | 92 | case BIT5_B: M_BIT(5,R->BC.B.h);break; case BIT5_C: M_BIT(5,R->BC.B.l);break; 93 | case BIT5_D: M_BIT(5,R->DE.B.h);break; case BIT5_E: M_BIT(5,R->DE.B.l);break; 94 | case BIT5_H: M_BIT(5,R->HL.B.h);break; case BIT5_L: M_BIT(5,R->HL.B.l);break; 95 | case BIT5_xHL: I=RdZ80(R->HL.W);M_BIT(5,I);break; 96 | case BIT5_A: M_BIT(5,R->AF.B.h);break; 97 | 98 | case BIT6_B: M_BIT(6,R->BC.B.h);break; case BIT6_C: M_BIT(6,R->BC.B.l);break; 99 | case BIT6_D: M_BIT(6,R->DE.B.h);break; case BIT6_E: M_BIT(6,R->DE.B.l);break; 100 | case BIT6_H: M_BIT(6,R->HL.B.h);break; case BIT6_L: M_BIT(6,R->HL.B.l);break; 101 | case BIT6_xHL: I=RdZ80(R->HL.W);M_BIT(6,I);break; 102 | case BIT6_A: M_BIT(6,R->AF.B.h);break; 103 | 104 | case BIT7_B: M_BIT(7,R->BC.B.h);break; case BIT7_C: M_BIT(7,R->BC.B.l);break; 105 | case BIT7_D: M_BIT(7,R->DE.B.h);break; case BIT7_E: M_BIT(7,R->DE.B.l);break; 106 | case BIT7_H: M_BIT(7,R->HL.B.h);break; case BIT7_L: M_BIT(7,R->HL.B.l);break; 107 | case BIT7_xHL: I=RdZ80(R->HL.W);M_BIT(7,I);break; 108 | case BIT7_A: M_BIT(7,R->AF.B.h);break; 109 | 110 | case RES0_B: M_RES(0,R->BC.B.h);break; case RES0_C: M_RES(0,R->BC.B.l);break; 111 | case RES0_D: M_RES(0,R->DE.B.h);break; case RES0_E: M_RES(0,R->DE.B.l);break; 112 | case RES0_H: M_RES(0,R->HL.B.h);break; case RES0_L: M_RES(0,R->HL.B.l);break; 113 | case RES0_xHL: I=RdZ80(R->HL.W);M_RES(0,I);WrZ80(R->HL.W,I);break; 114 | case RES0_A: M_RES(0,R->AF.B.h);break; 115 | 116 | case RES1_B: M_RES(1,R->BC.B.h);break; case RES1_C: M_RES(1,R->BC.B.l);break; 117 | case RES1_D: M_RES(1,R->DE.B.h);break; case RES1_E: M_RES(1,R->DE.B.l);break; 118 | case RES1_H: M_RES(1,R->HL.B.h);break; case RES1_L: M_RES(1,R->HL.B.l);break; 119 | case RES1_xHL: I=RdZ80(R->HL.W);M_RES(1,I);WrZ80(R->HL.W,I);break; 120 | case RES1_A: M_RES(1,R->AF.B.h);break; 121 | 122 | case RES2_B: M_RES(2,R->BC.B.h);break; case RES2_C: M_RES(2,R->BC.B.l);break; 123 | case RES2_D: M_RES(2,R->DE.B.h);break; case RES2_E: M_RES(2,R->DE.B.l);break; 124 | case RES2_H: M_RES(2,R->HL.B.h);break; case RES2_L: M_RES(2,R->HL.B.l);break; 125 | case RES2_xHL: I=RdZ80(R->HL.W);M_RES(2,I);WrZ80(R->HL.W,I);break; 126 | case RES2_A: M_RES(2,R->AF.B.h);break; 127 | 128 | case RES3_B: M_RES(3,R->BC.B.h);break; case RES3_C: M_RES(3,R->BC.B.l);break; 129 | case RES3_D: M_RES(3,R->DE.B.h);break; case RES3_E: M_RES(3,R->DE.B.l);break; 130 | case RES3_H: M_RES(3,R->HL.B.h);break; case RES3_L: M_RES(3,R->HL.B.l);break; 131 | case RES3_xHL: I=RdZ80(R->HL.W);M_RES(3,I);WrZ80(R->HL.W,I);break; 132 | case RES3_A: M_RES(3,R->AF.B.h);break; 133 | 134 | case RES4_B: M_RES(4,R->BC.B.h);break; case RES4_C: M_RES(4,R->BC.B.l);break; 135 | case RES4_D: M_RES(4,R->DE.B.h);break; case RES4_E: M_RES(4,R->DE.B.l);break; 136 | case RES4_H: M_RES(4,R->HL.B.h);break; case RES4_L: M_RES(4,R->HL.B.l);break; 137 | case RES4_xHL: I=RdZ80(R->HL.W);M_RES(4,I);WrZ80(R->HL.W,I);break; 138 | case RES4_A: M_RES(4,R->AF.B.h);break; 139 | 140 | case RES5_B: M_RES(5,R->BC.B.h);break; case RES5_C: M_RES(5,R->BC.B.l);break; 141 | case RES5_D: M_RES(5,R->DE.B.h);break; case RES5_E: M_RES(5,R->DE.B.l);break; 142 | case RES5_H: M_RES(5,R->HL.B.h);break; case RES5_L: M_RES(5,R->HL.B.l);break; 143 | case RES5_xHL: I=RdZ80(R->HL.W);M_RES(5,I);WrZ80(R->HL.W,I);break; 144 | case RES5_A: M_RES(5,R->AF.B.h);break; 145 | 146 | case RES6_B: M_RES(6,R->BC.B.h);break; case RES6_C: M_RES(6,R->BC.B.l);break; 147 | case RES6_D: M_RES(6,R->DE.B.h);break; case RES6_E: M_RES(6,R->DE.B.l);break; 148 | case RES6_H: M_RES(6,R->HL.B.h);break; case RES6_L: M_RES(6,R->HL.B.l);break; 149 | case RES6_xHL: I=RdZ80(R->HL.W);M_RES(6,I);WrZ80(R->HL.W,I);break; 150 | case RES6_A: M_RES(6,R->AF.B.h);break; 151 | 152 | case RES7_B: M_RES(7,R->BC.B.h);break; case RES7_C: M_RES(7,R->BC.B.l);break; 153 | case RES7_D: M_RES(7,R->DE.B.h);break; case RES7_E: M_RES(7,R->DE.B.l);break; 154 | case RES7_H: M_RES(7,R->HL.B.h);break; case RES7_L: M_RES(7,R->HL.B.l);break; 155 | case RES7_xHL: I=RdZ80(R->HL.W);M_RES(7,I);WrZ80(R->HL.W,I);break; 156 | case RES7_A: M_RES(7,R->AF.B.h);break; 157 | 158 | case SET0_B: M_SET(0,R->BC.B.h);break; case SET0_C: M_SET(0,R->BC.B.l);break; 159 | case SET0_D: M_SET(0,R->DE.B.h);break; case SET0_E: M_SET(0,R->DE.B.l);break; 160 | case SET0_H: M_SET(0,R->HL.B.h);break; case SET0_L: M_SET(0,R->HL.B.l);break; 161 | case SET0_xHL: I=RdZ80(R->HL.W);M_SET(0,I);WrZ80(R->HL.W,I);break; 162 | case SET0_A: M_SET(0,R->AF.B.h);break; 163 | 164 | case SET1_B: M_SET(1,R->BC.B.h);break; case SET1_C: M_SET(1,R->BC.B.l);break; 165 | case SET1_D: M_SET(1,R->DE.B.h);break; case SET1_E: M_SET(1,R->DE.B.l);break; 166 | case SET1_H: M_SET(1,R->HL.B.h);break; case SET1_L: M_SET(1,R->HL.B.l);break; 167 | case SET1_xHL: I=RdZ80(R->HL.W);M_SET(1,I);WrZ80(R->HL.W,I);break; 168 | case SET1_A: M_SET(1,R->AF.B.h);break; 169 | 170 | case SET2_B: M_SET(2,R->BC.B.h);break; case SET2_C: M_SET(2,R->BC.B.l);break; 171 | case SET2_D: M_SET(2,R->DE.B.h);break; case SET2_E: M_SET(2,R->DE.B.l);break; 172 | case SET2_H: M_SET(2,R->HL.B.h);break; case SET2_L: M_SET(2,R->HL.B.l);break; 173 | case SET2_xHL: I=RdZ80(R->HL.W);M_SET(2,I);WrZ80(R->HL.W,I);break; 174 | case SET2_A: M_SET(2,R->AF.B.h);break; 175 | 176 | case SET3_B: M_SET(3,R->BC.B.h);break; case SET3_C: M_SET(3,R->BC.B.l);break; 177 | case SET3_D: M_SET(3,R->DE.B.h);break; case SET3_E: M_SET(3,R->DE.B.l);break; 178 | case SET3_H: M_SET(3,R->HL.B.h);break; case SET3_L: M_SET(3,R->HL.B.l);break; 179 | case SET3_xHL: I=RdZ80(R->HL.W);M_SET(3,I);WrZ80(R->HL.W,I);break; 180 | case SET3_A: M_SET(3,R->AF.B.h);break; 181 | 182 | case SET4_B: M_SET(4,R->BC.B.h);break; case SET4_C: M_SET(4,R->BC.B.l);break; 183 | case SET4_D: M_SET(4,R->DE.B.h);break; case SET4_E: M_SET(4,R->DE.B.l);break; 184 | case SET4_H: M_SET(4,R->HL.B.h);break; case SET4_L: M_SET(4,R->HL.B.l);break; 185 | case SET4_xHL: I=RdZ80(R->HL.W);M_SET(4,I);WrZ80(R->HL.W,I);break; 186 | case SET4_A: M_SET(4,R->AF.B.h);break; 187 | 188 | case SET5_B: M_SET(5,R->BC.B.h);break; case SET5_C: M_SET(5,R->BC.B.l);break; 189 | case SET5_D: M_SET(5,R->DE.B.h);break; case SET5_E: M_SET(5,R->DE.B.l);break; 190 | case SET5_H: M_SET(5,R->HL.B.h);break; case SET5_L: M_SET(5,R->HL.B.l);break; 191 | case SET5_xHL: I=RdZ80(R->HL.W);M_SET(5,I);WrZ80(R->HL.W,I);break; 192 | case SET5_A: M_SET(5,R->AF.B.h);break; 193 | 194 | case SET6_B: M_SET(6,R->BC.B.h);break; case SET6_C: M_SET(6,R->BC.B.l);break; 195 | case SET6_D: M_SET(6,R->DE.B.h);break; case SET6_E: M_SET(6,R->DE.B.l);break; 196 | case SET6_H: M_SET(6,R->HL.B.h);break; case SET6_L: M_SET(6,R->HL.B.l);break; 197 | case SET6_xHL: I=RdZ80(R->HL.W);M_SET(6,I);WrZ80(R->HL.W,I);break; 198 | case SET6_A: M_SET(6,R->AF.B.h);break; 199 | 200 | case SET7_B: M_SET(7,R->BC.B.h);break; case SET7_C: M_SET(7,R->BC.B.l);break; 201 | case SET7_D: M_SET(7,R->DE.B.h);break; case SET7_E: M_SET(7,R->DE.B.l);break; 202 | case SET7_H: M_SET(7,R->HL.B.h);break; case SET7_L: M_SET(7,R->HL.B.l);break; 203 | case SET7_xHL: I=RdZ80(R->HL.W);M_SET(7,I);WrZ80(R->HL.W,I);break; 204 | case SET7_A: M_SET(7,R->AF.B.h);break; 205 | -------------------------------------------------------------------------------- /src/Codes.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** Codes.h **/ 4 | /** **/ 5 | /** This file contains implementation for the main table of **/ 6 | /** Z80 commands. It is included from Z80.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break; 15 | case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break; 16 | case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break; 17 | case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break; 18 | 19 | case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break; 20 | case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break; 21 | case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break; 22 | case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break; 23 | case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break; 24 | case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break; 25 | case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break; 26 | case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break; 27 | 28 | case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break; 29 | case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break; 30 | case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break; 31 | case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break; 32 | case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break; 33 | case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break; 34 | case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break; 35 | case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break; 36 | 37 | case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 38 | case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 39 | case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 40 | case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 41 | case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 42 | case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 43 | case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 44 | case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 45 | 46 | case ADD_B: M_ADD(R->BC.B.h);break; 47 | case ADD_C: M_ADD(R->BC.B.l);break; 48 | case ADD_D: M_ADD(R->DE.B.h);break; 49 | case ADD_E: M_ADD(R->DE.B.l);break; 50 | case ADD_H: M_ADD(R->HL.B.h);break; 51 | case ADD_L: M_ADD(R->HL.B.l);break; 52 | case ADD_A: M_ADD(R->AF.B.h);break; 53 | case ADD_xHL: I=RdZ80(R->HL.W);M_ADD(I);break; 54 | case ADD_BYTE: I=OpZ80(R->PC.W++);M_ADD(I);break; 55 | 56 | case SUB_B: M_SUB(R->BC.B.h);break; 57 | case SUB_C: M_SUB(R->BC.B.l);break; 58 | case SUB_D: M_SUB(R->DE.B.h);break; 59 | case SUB_E: M_SUB(R->DE.B.l);break; 60 | case SUB_H: M_SUB(R->HL.B.h);break; 61 | case SUB_L: M_SUB(R->HL.B.l);break; 62 | case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break; 63 | case SUB_xHL: I=RdZ80(R->HL.W);M_SUB(I);break; 64 | case SUB_BYTE: I=OpZ80(R->PC.W++);M_SUB(I);break; 65 | 66 | case AND_B: M_AND(R->BC.B.h);break; 67 | case AND_C: M_AND(R->BC.B.l);break; 68 | case AND_D: M_AND(R->DE.B.h);break; 69 | case AND_E: M_AND(R->DE.B.l);break; 70 | case AND_H: M_AND(R->HL.B.h);break; 71 | case AND_L: M_AND(R->HL.B.l);break; 72 | case AND_A: M_AND(R->AF.B.h);break; 73 | case AND_xHL: I=RdZ80(R->HL.W);M_AND(I);break; 74 | case AND_BYTE: I=OpZ80(R->PC.W++);M_AND(I);break; 75 | 76 | case OR_B: M_OR(R->BC.B.h);break; 77 | case OR_C: M_OR(R->BC.B.l);break; 78 | case OR_D: M_OR(R->DE.B.h);break; 79 | case OR_E: M_OR(R->DE.B.l);break; 80 | case OR_H: M_OR(R->HL.B.h);break; 81 | case OR_L: M_OR(R->HL.B.l);break; 82 | case OR_A: M_OR(R->AF.B.h);break; 83 | case OR_xHL: I=RdZ80(R->HL.W);M_OR(I);break; 84 | case OR_BYTE: I=OpZ80(R->PC.W++);M_OR(I);break; 85 | 86 | case ADC_B: M_ADC(R->BC.B.h);break; 87 | case ADC_C: M_ADC(R->BC.B.l);break; 88 | case ADC_D: M_ADC(R->DE.B.h);break; 89 | case ADC_E: M_ADC(R->DE.B.l);break; 90 | case ADC_H: M_ADC(R->HL.B.h);break; 91 | case ADC_L: M_ADC(R->HL.B.l);break; 92 | case ADC_A: M_ADC(R->AF.B.h);break; 93 | case ADC_xHL: I=RdZ80(R->HL.W);M_ADC(I);break; 94 | case ADC_BYTE: I=OpZ80(R->PC.W++);M_ADC(I);break; 95 | 96 | case SBC_B: M_SBC(R->BC.B.h);break; 97 | case SBC_C: M_SBC(R->BC.B.l);break; 98 | case SBC_D: M_SBC(R->DE.B.h);break; 99 | case SBC_E: M_SBC(R->DE.B.l);break; 100 | case SBC_H: M_SBC(R->HL.B.h);break; 101 | case SBC_L: M_SBC(R->HL.B.l);break; 102 | case SBC_A: M_SBC(R->AF.B.h);break; 103 | case SBC_xHL: I=RdZ80(R->HL.W);M_SBC(I);break; 104 | case SBC_BYTE: I=OpZ80(R->PC.W++);M_SBC(I);break; 105 | 106 | case XOR_B: M_XOR(R->BC.B.h);break; 107 | case XOR_C: M_XOR(R->BC.B.l);break; 108 | case XOR_D: M_XOR(R->DE.B.h);break; 109 | case XOR_E: M_XOR(R->DE.B.l);break; 110 | case XOR_H: M_XOR(R->HL.B.h);break; 111 | case XOR_L: M_XOR(R->HL.B.l);break; 112 | case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break; 113 | case XOR_xHL: I=RdZ80(R->HL.W);M_XOR(I);break; 114 | case XOR_BYTE: I=OpZ80(R->PC.W++);M_XOR(I);break; 115 | 116 | case CP_B: M_CP(R->BC.B.h);break; 117 | case CP_C: M_CP(R->BC.B.l);break; 118 | case CP_D: M_CP(R->DE.B.h);break; 119 | case CP_E: M_CP(R->DE.B.l);break; 120 | case CP_H: M_CP(R->HL.B.h);break; 121 | case CP_L: M_CP(R->HL.B.l);break; 122 | case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break; 123 | case CP_xHL: I=RdZ80(R->HL.W);M_CP(I);break; 124 | case CP_BYTE: I=OpZ80(R->PC.W++);M_CP(I);break; 125 | 126 | case LD_BC_WORD: M_LDWORD(BC);break; 127 | case LD_DE_WORD: M_LDWORD(DE);break; 128 | case LD_HL_WORD: M_LDWORD(HL);break; 129 | case LD_SP_WORD: M_LDWORD(SPtr);break; 130 | 131 | case LD_PC_HL: R->PC.W=R->HL.W;JumpZ80(R->PC.W);break; 132 | case LD_SP_HL: R->SPtr.W=R->HL.W;break; 133 | case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break; 134 | case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break; 135 | 136 | case ADD_HL_BC: M_ADDW(HL,BC);break; 137 | case ADD_HL_DE: M_ADDW(HL,DE);break; 138 | case ADD_HL_HL: M_ADDW(HL,HL);break; 139 | case ADD_HL_SP: M_ADDW(HL,SPtr);break; 140 | 141 | case DEC_BC: R->BC.W--;break; 142 | case DEC_DE: R->DE.W--;break; 143 | case DEC_HL: R->HL.W--;break; 144 | case DEC_SP: R->SPtr.W--;break; 145 | 146 | case INC_BC: R->BC.W++;break; 147 | case INC_DE: R->DE.W++;break; 148 | case INC_HL: R->HL.W++;break; 149 | case INC_SP: R->SPtr.W++;break; 150 | 151 | case DEC_B: M_DEC(R->BC.B.h);break; 152 | case DEC_C: M_DEC(R->BC.B.l);break; 153 | case DEC_D: M_DEC(R->DE.B.h);break; 154 | case DEC_E: M_DEC(R->DE.B.l);break; 155 | case DEC_H: M_DEC(R->HL.B.h);break; 156 | case DEC_L: M_DEC(R->HL.B.l);break; 157 | case DEC_A: M_DEC(R->AF.B.h);break; 158 | case DEC_xHL: I=RdZ80(R->HL.W);M_DEC(I);WrZ80(R->HL.W,I);break; 159 | 160 | case INC_B: M_INC(R->BC.B.h);break; 161 | case INC_C: M_INC(R->BC.B.l);break; 162 | case INC_D: M_INC(R->DE.B.h);break; 163 | case INC_E: M_INC(R->DE.B.l);break; 164 | case INC_H: M_INC(R->HL.B.h);break; 165 | case INC_L: M_INC(R->HL.B.l);break; 166 | case INC_A: M_INC(R->AF.B.h);break; 167 | case INC_xHL: I=RdZ80(R->HL.W);M_INC(I);WrZ80(R->HL.W,I);break; 168 | 169 | case RLCA: 170 | I=R->AF.B.h&0x80? C_FLAG:0; 171 | R->AF.B.h=(R->AF.B.h<<1)|I; 172 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 173 | break; 174 | case RLA: 175 | I=R->AF.B.h&0x80? C_FLAG:0; 176 | R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG); 177 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 178 | break; 179 | case RRCA: 180 | I=R->AF.B.h&0x01; 181 | R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0); 182 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 183 | break; 184 | case RRA: 185 | I=R->AF.B.h&0x01; 186 | R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0); 187 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 188 | break; 189 | 190 | case RST00: M_RST(0x0000);break; 191 | case RST08: M_RST(0x0008);break; 192 | case RST10: M_RST(0x0010);break; 193 | case RST18: M_RST(0x0018);break; 194 | case RST20: M_RST(0x0020);break; 195 | case RST28: M_RST(0x0028);break; 196 | case RST30: M_RST(0x0030);break; 197 | case RST38: M_RST(0x0038);break; 198 | 199 | case PUSH_BC: M_PUSH(BC);break; 200 | case PUSH_DE: M_PUSH(DE);break; 201 | case PUSH_HL: M_PUSH(HL);break; 202 | case PUSH_AF: M_PUSH(AF);break; 203 | 204 | case POP_BC: M_POP(BC);break; 205 | case POP_DE: M_POP(DE);break; 206 | case POP_HL: M_POP(HL);break; 207 | case POP_AF: M_POP(AF);break; 208 | 209 | case DJNZ: if(--R->BC.B.h) { R->ICount-=5;M_JR; } else R->PC.W++;break; 210 | case JP: M_JP;break; 211 | case JR: M_JR;break; 212 | case CALL: M_CALL;break; 213 | case RET: M_RET;break; 214 | case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break; 215 | case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break; 216 | case NOP: break; 217 | case OUTA: I=OpZ80(R->PC.W++);OutZ80(I|(R->AF.W&0xFF00),R->AF.B.h);break; 218 | case INA: I=OpZ80(R->PC.W++);R->AF.B.h=InZ80(I|(R->AF.W&0xFF00));break; 219 | 220 | case HALT: 221 | R->PC.W--; 222 | R->IFF|=IFF_HALT; 223 | R->IBackup=0; 224 | R->ICount=0; 225 | break; 226 | 227 | case DI: 228 | if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1; 229 | R->IFF&=~(IFF_1|IFF_2|IFF_EI); 230 | break; 231 | 232 | case EI: 233 | if(!(R->IFF&(IFF_1|IFF_EI))) 234 | { 235 | R->IFF|=IFF_2|IFF_EI; 236 | R->IBackup=R->ICount; 237 | R->ICount=1; 238 | } 239 | break; 240 | 241 | case CCF: 242 | R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG); 243 | R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG; 244 | break; 245 | 246 | case EXX: 247 | J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W; 248 | J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W; 249 | J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W; 250 | break; 251 | 252 | case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break; 253 | case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break; 254 | 255 | case LD_B_B: R->BC.B.h=R->BC.B.h;break; 256 | case LD_C_B: R->BC.B.l=R->BC.B.h;break; 257 | case LD_D_B: R->DE.B.h=R->BC.B.h;break; 258 | case LD_E_B: R->DE.B.l=R->BC.B.h;break; 259 | case LD_H_B: R->HL.B.h=R->BC.B.h;break; 260 | case LD_L_B: R->HL.B.l=R->BC.B.h;break; 261 | case LD_A_B: R->AF.B.h=R->BC.B.h;break; 262 | case LD_xHL_B: WrZ80(R->HL.W,R->BC.B.h);break; 263 | 264 | case LD_B_C: R->BC.B.h=R->BC.B.l;break; 265 | case LD_C_C: R->BC.B.l=R->BC.B.l;break; 266 | case LD_D_C: R->DE.B.h=R->BC.B.l;break; 267 | case LD_E_C: R->DE.B.l=R->BC.B.l;break; 268 | case LD_H_C: R->HL.B.h=R->BC.B.l;break; 269 | case LD_L_C: R->HL.B.l=R->BC.B.l;break; 270 | case LD_A_C: R->AF.B.h=R->BC.B.l;break; 271 | case LD_xHL_C: WrZ80(R->HL.W,R->BC.B.l);break; 272 | 273 | case LD_B_D: R->BC.B.h=R->DE.B.h;break; 274 | case LD_C_D: R->BC.B.l=R->DE.B.h;break; 275 | case LD_D_D: R->DE.B.h=R->DE.B.h;break; 276 | case LD_E_D: R->DE.B.l=R->DE.B.h;break; 277 | case LD_H_D: R->HL.B.h=R->DE.B.h;break; 278 | case LD_L_D: R->HL.B.l=R->DE.B.h;break; 279 | case LD_A_D: R->AF.B.h=R->DE.B.h;break; 280 | case LD_xHL_D: WrZ80(R->HL.W,R->DE.B.h);break; 281 | 282 | case LD_B_E: R->BC.B.h=R->DE.B.l;break; 283 | case LD_C_E: R->BC.B.l=R->DE.B.l;break; 284 | case LD_D_E: R->DE.B.h=R->DE.B.l;break; 285 | case LD_E_E: R->DE.B.l=R->DE.B.l;break; 286 | case LD_H_E: R->HL.B.h=R->DE.B.l;break; 287 | case LD_L_E: R->HL.B.l=R->DE.B.l;break; 288 | case LD_A_E: R->AF.B.h=R->DE.B.l;break; 289 | case LD_xHL_E: WrZ80(R->HL.W,R->DE.B.l);break; 290 | 291 | case LD_B_H: R->BC.B.h=R->HL.B.h;break; 292 | case LD_C_H: R->BC.B.l=R->HL.B.h;break; 293 | case LD_D_H: R->DE.B.h=R->HL.B.h;break; 294 | case LD_E_H: R->DE.B.l=R->HL.B.h;break; 295 | case LD_H_H: R->HL.B.h=R->HL.B.h;break; 296 | case LD_L_H: R->HL.B.l=R->HL.B.h;break; 297 | case LD_A_H: R->AF.B.h=R->HL.B.h;break; 298 | case LD_xHL_H: WrZ80(R->HL.W,R->HL.B.h);break; 299 | 300 | case LD_B_L: R->BC.B.h=R->HL.B.l;break; 301 | case LD_C_L: R->BC.B.l=R->HL.B.l;break; 302 | case LD_D_L: R->DE.B.h=R->HL.B.l;break; 303 | case LD_E_L: R->DE.B.l=R->HL.B.l;break; 304 | case LD_H_L: R->HL.B.h=R->HL.B.l;break; 305 | case LD_L_L: R->HL.B.l=R->HL.B.l;break; 306 | case LD_A_L: R->AF.B.h=R->HL.B.l;break; 307 | case LD_xHL_L: WrZ80(R->HL.W,R->HL.B.l);break; 308 | 309 | case LD_B_A: R->BC.B.h=R->AF.B.h;break; 310 | case LD_C_A: R->BC.B.l=R->AF.B.h;break; 311 | case LD_D_A: R->DE.B.h=R->AF.B.h;break; 312 | case LD_E_A: R->DE.B.l=R->AF.B.h;break; 313 | case LD_H_A: R->HL.B.h=R->AF.B.h;break; 314 | case LD_L_A: R->HL.B.l=R->AF.B.h;break; 315 | case LD_A_A: R->AF.B.h=R->AF.B.h;break; 316 | case LD_xHL_A: WrZ80(R->HL.W,R->AF.B.h);break; 317 | 318 | case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break; 319 | case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break; 320 | 321 | case LD_B_xHL: R->BC.B.h=RdZ80(R->HL.W);break; 322 | case LD_C_xHL: R->BC.B.l=RdZ80(R->HL.W);break; 323 | case LD_D_xHL: R->DE.B.h=RdZ80(R->HL.W);break; 324 | case LD_E_xHL: R->DE.B.l=RdZ80(R->HL.W);break; 325 | case LD_H_xHL: R->HL.B.h=RdZ80(R->HL.W);break; 326 | case LD_L_xHL: R->HL.B.l=RdZ80(R->HL.W);break; 327 | case LD_A_xHL: R->AF.B.h=RdZ80(R->HL.W);break; 328 | 329 | case LD_B_BYTE: R->BC.B.h=OpZ80(R->PC.W++);break; 330 | case LD_C_BYTE: R->BC.B.l=OpZ80(R->PC.W++);break; 331 | case LD_D_BYTE: R->DE.B.h=OpZ80(R->PC.W++);break; 332 | case LD_E_BYTE: R->DE.B.l=OpZ80(R->PC.W++);break; 333 | case LD_H_BYTE: R->HL.B.h=OpZ80(R->PC.W++);break; 334 | case LD_L_BYTE: R->HL.B.l=OpZ80(R->PC.W++);break; 335 | case LD_A_BYTE: R->AF.B.h=OpZ80(R->PC.W++);break; 336 | case LD_xHL_BYTE: WrZ80(R->HL.W,OpZ80(R->PC.W++));break; 337 | 338 | case LD_xWORD_HL: 339 | J.B.l=OpZ80(R->PC.W++); 340 | J.B.h=OpZ80(R->PC.W++); 341 | WrZ80(J.W++,R->HL.B.l); 342 | WrZ80(J.W,R->HL.B.h); 343 | break; 344 | 345 | case LD_HL_xWORD: 346 | J.B.l=OpZ80(R->PC.W++); 347 | J.B.h=OpZ80(R->PC.W++); 348 | R->HL.B.l=RdZ80(J.W++); 349 | R->HL.B.h=RdZ80(J.W); 350 | break; 351 | 352 | case LD_A_xWORD: 353 | J.B.l=OpZ80(R->PC.W++); 354 | J.B.h=OpZ80(R->PC.W++); 355 | R->AF.B.h=RdZ80(J.W); 356 | break; 357 | 358 | case LD_xWORD_A: 359 | J.B.l=OpZ80(R->PC.W++); 360 | J.B.h=OpZ80(R->PC.W++); 361 | WrZ80(J.W,R->AF.B.h); 362 | break; 363 | 364 | case EX_HL_xSP: 365 | J.B.l=RdZ80(R->SPtr.W);WrZ80(R->SPtr.W++,R->HL.B.l); 366 | J.B.h=RdZ80(R->SPtr.W);WrZ80(R->SPtr.W--,R->HL.B.h); 367 | R->HL.W=J.W; 368 | break; 369 | 370 | case DAA: 371 | J.W=R->AF.B.h; 372 | if(R->AF.B.l&C_FLAG) J.W|=256; 373 | if(R->AF.B.l&H_FLAG) J.W|=512; 374 | if(R->AF.B.l&N_FLAG) J.W|=1024; 375 | R->AF.W=DAATable[J.W]; 376 | break; 377 | 378 | default: 379 | if(R->TrapBadOps) 380 | printf 381 | ( 382 | "[Z80 %lX] Unrecognized instruction: %02X at PC=%04X\n", 383 | (long)R->User,OpZ80(R->PC.W-1),R->PC.W-1 384 | ); 385 | break; 386 | -------------------------------------------------------------------------------- /src/CodesXX.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** CodesXX.h **/ 4 | /** **/ 5 | /** This file contains implementation for FD/DD tables of **/ 6 | /** Z80 commands. It is included from Z80.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break; 15 | case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break; 16 | case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break; 17 | case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break; 18 | 19 | case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break; 20 | case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break; 21 | case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break; 22 | case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break; 23 | case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break; 24 | case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break; 25 | case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break; 26 | case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break; 27 | 28 | case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break; 29 | case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break; 30 | case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break; 31 | case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break; 32 | case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break; 33 | case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break; 34 | case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break; 35 | case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break; 36 | 37 | case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 38 | case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 39 | case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 40 | case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break; 41 | case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 42 | case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 43 | case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 44 | case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break; 45 | 46 | case ADD_B: M_ADD(R->BC.B.h);break; 47 | case ADD_C: M_ADD(R->BC.B.l);break; 48 | case ADD_D: M_ADD(R->DE.B.h);break; 49 | case ADD_E: M_ADD(R->DE.B.l);break; 50 | case ADD_H: M_ADD(R->XX.B.h);break; 51 | case ADD_L: M_ADD(R->XX.B.l);break; 52 | case ADD_A: M_ADD(R->AF.B.h);break; 53 | case ADD_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 54 | M_ADD(I);break; 55 | case ADD_BYTE: I=OpZ80(R->PC.W++);M_ADD(I);break; 56 | 57 | case SUB_B: M_SUB(R->BC.B.h);break; 58 | case SUB_C: M_SUB(R->BC.B.l);break; 59 | case SUB_D: M_SUB(R->DE.B.h);break; 60 | case SUB_E: M_SUB(R->DE.B.l);break; 61 | case SUB_H: M_SUB(R->XX.B.h);break; 62 | case SUB_L: M_SUB(R->XX.B.l);break; 63 | case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break; 64 | case SUB_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 65 | M_SUB(I);break; 66 | case SUB_BYTE: I=OpZ80(R->PC.W++);M_SUB(I);break; 67 | 68 | case AND_B: M_AND(R->BC.B.h);break; 69 | case AND_C: M_AND(R->BC.B.l);break; 70 | case AND_D: M_AND(R->DE.B.h);break; 71 | case AND_E: M_AND(R->DE.B.l);break; 72 | case AND_H: M_AND(R->XX.B.h);break; 73 | case AND_L: M_AND(R->XX.B.l);break; 74 | case AND_A: M_AND(R->AF.B.h);break; 75 | case AND_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 76 | M_AND(I);break; 77 | case AND_BYTE: I=OpZ80(R->PC.W++);M_AND(I);break; 78 | 79 | case OR_B: M_OR(R->BC.B.h);break; 80 | case OR_C: M_OR(R->BC.B.l);break; 81 | case OR_D: M_OR(R->DE.B.h);break; 82 | case OR_E: M_OR(R->DE.B.l);break; 83 | case OR_H: M_OR(R->XX.B.h);break; 84 | case OR_L: M_OR(R->XX.B.l);break; 85 | case OR_A: M_OR(R->AF.B.h);break; 86 | case OR_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 87 | M_OR(I);break; 88 | case OR_BYTE: I=OpZ80(R->PC.W++);M_OR(I);break; 89 | 90 | case ADC_B: M_ADC(R->BC.B.h);break; 91 | case ADC_C: M_ADC(R->BC.B.l);break; 92 | case ADC_D: M_ADC(R->DE.B.h);break; 93 | case ADC_E: M_ADC(R->DE.B.l);break; 94 | case ADC_H: M_ADC(R->XX.B.h);break; 95 | case ADC_L: M_ADC(R->XX.B.l);break; 96 | case ADC_A: M_ADC(R->AF.B.h);break; 97 | case ADC_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 98 | M_ADC(I);break; 99 | case ADC_BYTE: I=OpZ80(R->PC.W++);M_ADC(I);break; 100 | 101 | case SBC_B: M_SBC(R->BC.B.h);break; 102 | case SBC_C: M_SBC(R->BC.B.l);break; 103 | case SBC_D: M_SBC(R->DE.B.h);break; 104 | case SBC_E: M_SBC(R->DE.B.l);break; 105 | case SBC_H: M_SBC(R->XX.B.h);break; 106 | case SBC_L: M_SBC(R->XX.B.l);break; 107 | case SBC_A: M_SBC(R->AF.B.h);break; 108 | case SBC_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 109 | M_SBC(I);break; 110 | case SBC_BYTE: I=OpZ80(R->PC.W++);M_SBC(I);break; 111 | 112 | case XOR_B: M_XOR(R->BC.B.h);break; 113 | case XOR_C: M_XOR(R->BC.B.l);break; 114 | case XOR_D: M_XOR(R->DE.B.h);break; 115 | case XOR_E: M_XOR(R->DE.B.l);break; 116 | case XOR_H: M_XOR(R->XX.B.h);break; 117 | case XOR_L: M_XOR(R->XX.B.l);break; 118 | case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break; 119 | case XOR_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 120 | M_XOR(I);break; 121 | case XOR_BYTE: I=OpZ80(R->PC.W++);M_XOR(I);break; 122 | 123 | case CP_B: M_CP(R->BC.B.h);break; 124 | case CP_C: M_CP(R->BC.B.l);break; 125 | case CP_D: M_CP(R->DE.B.h);break; 126 | case CP_E: M_CP(R->DE.B.l);break; 127 | case CP_H: M_CP(R->XX.B.h);break; 128 | case CP_L: M_CP(R->XX.B.l);break; 129 | case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break; 130 | case CP_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++)); 131 | M_CP(I);break; 132 | case CP_BYTE: I=OpZ80(R->PC.W++);M_CP(I);break; 133 | 134 | case LD_BC_WORD: M_LDWORD(BC);break; 135 | case LD_DE_WORD: M_LDWORD(DE);break; 136 | case LD_HL_WORD: M_LDWORD(XX);break; 137 | case LD_SP_WORD: M_LDWORD(SPtr);break; 138 | 139 | case LD_PC_HL: R->PC.W=R->XX.W;JumpZ80(R->PC.W);break; 140 | case LD_SP_HL: R->SPtr.W=R->XX.W;break; 141 | case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break; 142 | case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break; 143 | 144 | case ADD_HL_BC: M_ADDW(XX,BC);break; 145 | case ADD_HL_DE: M_ADDW(XX,DE);break; 146 | case ADD_HL_HL: M_ADDW(XX,XX);break; 147 | case ADD_HL_SP: M_ADDW(XX,SPtr);break; 148 | 149 | case DEC_BC: R->BC.W--;break; 150 | case DEC_DE: R->DE.W--;break; 151 | case DEC_HL: R->XX.W--;break; 152 | case DEC_SP: R->SPtr.W--;break; 153 | 154 | case INC_BC: R->BC.W++;break; 155 | case INC_DE: R->DE.W++;break; 156 | case INC_HL: R->XX.W++;break; 157 | case INC_SP: R->SPtr.W++;break; 158 | 159 | case DEC_B: M_DEC(R->BC.B.h);break; 160 | case DEC_C: M_DEC(R->BC.B.l);break; 161 | case DEC_D: M_DEC(R->DE.B.h);break; 162 | case DEC_E: M_DEC(R->DE.B.l);break; 163 | case DEC_H: M_DEC(R->XX.B.h);break; 164 | case DEC_L: M_DEC(R->XX.B.l);break; 165 | case DEC_A: M_DEC(R->AF.B.h);break; 166 | case DEC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_DEC(I); 167 | WrZ80(R->XX.W+(offset)OpZ80(R->PC.W++),I); 168 | break; 169 | 170 | case INC_B: M_INC(R->BC.B.h);break; 171 | case INC_C: M_INC(R->BC.B.l);break; 172 | case INC_D: M_INC(R->DE.B.h);break; 173 | case INC_E: M_INC(R->DE.B.l);break; 174 | case INC_H: M_INC(R->XX.B.h);break; 175 | case INC_L: M_INC(R->XX.B.l);break; 176 | case INC_A: M_INC(R->AF.B.h);break; 177 | case INC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_INC(I); 178 | WrZ80(R->XX.W+(offset)OpZ80(R->PC.W++),I); 179 | break; 180 | 181 | case RLCA: 182 | I=(R->AF.B.h&0x80? C_FLAG:0); 183 | R->AF.B.h=(R->AF.B.h<<1)|I; 184 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 185 | break; 186 | case RLA: 187 | I=(R->AF.B.h&0x80? C_FLAG:0); 188 | R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG); 189 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 190 | break; 191 | case RRCA: 192 | I=R->AF.B.h&0x01; 193 | R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0); 194 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 195 | break; 196 | case RRA: 197 | I=R->AF.B.h&0x01; 198 | R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0); 199 | R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I; 200 | break; 201 | 202 | case RST00: M_RST(0x0000);break; 203 | case RST08: M_RST(0x0008);break; 204 | case RST10: M_RST(0x0010);break; 205 | case RST18: M_RST(0x0018);break; 206 | case RST20: M_RST(0x0020);break; 207 | case RST28: M_RST(0x0028);break; 208 | case RST30: M_RST(0x0030);break; 209 | case RST38: M_RST(0x0038);break; 210 | 211 | case PUSH_BC: M_PUSH(BC);break; 212 | case PUSH_DE: M_PUSH(DE);break; 213 | case PUSH_HL: M_PUSH(XX);break; 214 | case PUSH_AF: M_PUSH(AF);break; 215 | 216 | case POP_BC: M_POP(BC);break; 217 | case POP_DE: M_POP(DE);break; 218 | case POP_HL: M_POP(XX);break; 219 | case POP_AF: M_POP(AF);break; 220 | 221 | case DJNZ: if(--R->BC.B.h) { R->ICount-=5;M_JR; } else R->PC.W++;break; 222 | case JP: M_JP;break; 223 | case JR: M_JR;break; 224 | case CALL: M_CALL;break; 225 | case RET: M_RET;break; 226 | case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break; 227 | case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break; 228 | case NOP: break; 229 | case OUTA: I=OpZ80(R->PC.W++);OutZ80(I|(R->AF.W&0xFF00),R->AF.B.h);break; 230 | case INA: I=OpZ80(R->PC.W++);R->AF.B.h=InZ80(I|(R->AF.W&0xFF00));break; 231 | 232 | case HALT: 233 | R->PC.W--; 234 | R->IFF|=IFF_HALT; 235 | R->IBackup=0; 236 | R->ICount=0; 237 | break; 238 | 239 | case DI: 240 | if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1; 241 | R->IFF&=~(IFF_1|IFF_2|IFF_EI); 242 | break; 243 | 244 | case EI: 245 | if(!(R->IFF&(IFF_1|IFF_EI))) 246 | { 247 | R->IFF|=IFF_2|IFF_EI; 248 | R->IBackup=R->ICount; 249 | R->ICount=1; 250 | } 251 | break; 252 | 253 | case CCF: 254 | R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG); 255 | R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG; 256 | break; 257 | 258 | case EXX: 259 | J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W; 260 | J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W; 261 | J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W; 262 | break; 263 | 264 | case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break; 265 | case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break; 266 | 267 | case LD_B_B: R->BC.B.h=R->BC.B.h;break; 268 | case LD_C_B: R->BC.B.l=R->BC.B.h;break; 269 | case LD_D_B: R->DE.B.h=R->BC.B.h;break; 270 | case LD_E_B: R->DE.B.l=R->BC.B.h;break; 271 | case LD_H_B: R->XX.B.h=R->BC.B.h;break; 272 | case LD_L_B: R->XX.B.l=R->BC.B.h;break; 273 | case LD_A_B: R->AF.B.h=R->BC.B.h;break; 274 | case LD_xHL_B: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 275 | WrZ80(J.W,R->BC.B.h);break; 276 | 277 | case LD_B_C: R->BC.B.h=R->BC.B.l;break; 278 | case LD_C_C: R->BC.B.l=R->BC.B.l;break; 279 | case LD_D_C: R->DE.B.h=R->BC.B.l;break; 280 | case LD_E_C: R->DE.B.l=R->BC.B.l;break; 281 | case LD_H_C: R->XX.B.h=R->BC.B.l;break; 282 | case LD_L_C: R->XX.B.l=R->BC.B.l;break; 283 | case LD_A_C: R->AF.B.h=R->BC.B.l;break; 284 | case LD_xHL_C: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 285 | WrZ80(J.W,R->BC.B.l);break; 286 | 287 | case LD_B_D: R->BC.B.h=R->DE.B.h;break; 288 | case LD_C_D: R->BC.B.l=R->DE.B.h;break; 289 | case LD_D_D: R->DE.B.h=R->DE.B.h;break; 290 | case LD_E_D: R->DE.B.l=R->DE.B.h;break; 291 | case LD_H_D: R->XX.B.h=R->DE.B.h;break; 292 | case LD_L_D: R->XX.B.l=R->DE.B.h;break; 293 | case LD_A_D: R->AF.B.h=R->DE.B.h;break; 294 | case LD_xHL_D: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 295 | WrZ80(J.W,R->DE.B.h);break; 296 | 297 | case LD_B_E: R->BC.B.h=R->DE.B.l;break; 298 | case LD_C_E: R->BC.B.l=R->DE.B.l;break; 299 | case LD_D_E: R->DE.B.h=R->DE.B.l;break; 300 | case LD_E_E: R->DE.B.l=R->DE.B.l;break; 301 | case LD_H_E: R->XX.B.h=R->DE.B.l;break; 302 | case LD_L_E: R->XX.B.l=R->DE.B.l;break; 303 | case LD_A_E: R->AF.B.h=R->DE.B.l;break; 304 | case LD_xHL_E: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 305 | WrZ80(J.W,R->DE.B.l);break; 306 | 307 | case LD_B_H: R->BC.B.h=R->XX.B.h;break; 308 | case LD_C_H: R->BC.B.l=R->XX.B.h;break; 309 | case LD_D_H: R->DE.B.h=R->XX.B.h;break; 310 | case LD_E_H: R->DE.B.l=R->XX.B.h;break; 311 | case LD_H_H: R->XX.B.h=R->XX.B.h;break; 312 | case LD_L_H: R->XX.B.l=R->XX.B.h;break; 313 | case LD_A_H: R->AF.B.h=R->XX.B.h;break; 314 | case LD_xHL_H: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 315 | WrZ80(J.W,R->HL.B.h);break; 316 | 317 | case LD_B_L: R->BC.B.h=R->XX.B.l;break; 318 | case LD_C_L: R->BC.B.l=R->XX.B.l;break; 319 | case LD_D_L: R->DE.B.h=R->XX.B.l;break; 320 | case LD_E_L: R->DE.B.l=R->XX.B.l;break; 321 | case LD_H_L: R->XX.B.h=R->XX.B.l;break; 322 | case LD_L_L: R->XX.B.l=R->XX.B.l;break; 323 | case LD_A_L: R->AF.B.h=R->XX.B.l;break; 324 | case LD_xHL_L: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 325 | WrZ80(J.W,R->HL.B.l);break; 326 | 327 | case LD_B_A: R->BC.B.h=R->AF.B.h;break; 328 | case LD_C_A: R->BC.B.l=R->AF.B.h;break; 329 | case LD_D_A: R->DE.B.h=R->AF.B.h;break; 330 | case LD_E_A: R->DE.B.l=R->AF.B.h;break; 331 | case LD_H_A: R->XX.B.h=R->AF.B.h;break; 332 | case LD_L_A: R->XX.B.l=R->AF.B.h;break; 333 | case LD_A_A: R->AF.B.h=R->AF.B.h;break; 334 | case LD_xHL_A: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 335 | WrZ80(J.W,R->AF.B.h);break; 336 | 337 | case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break; 338 | case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break; 339 | 340 | case LD_B_xHL: R->BC.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break; 341 | case LD_C_xHL: R->BC.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break; 342 | case LD_D_xHL: R->DE.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break; 343 | case LD_E_xHL: R->DE.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break; 344 | case LD_H_xHL: R->HL.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break; 345 | case LD_L_xHL: R->HL.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break; 346 | case LD_A_xHL: R->AF.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break; 347 | 348 | case LD_B_BYTE: R->BC.B.h=OpZ80(R->PC.W++);break; 349 | case LD_C_BYTE: R->BC.B.l=OpZ80(R->PC.W++);break; 350 | case LD_D_BYTE: R->DE.B.h=OpZ80(R->PC.W++);break; 351 | case LD_E_BYTE: R->DE.B.l=OpZ80(R->PC.W++);break; 352 | case LD_H_BYTE: R->XX.B.h=OpZ80(R->PC.W++);break; 353 | case LD_L_BYTE: R->XX.B.l=OpZ80(R->PC.W++);break; 354 | case LD_A_BYTE: R->AF.B.h=OpZ80(R->PC.W++);break; 355 | case LD_xHL_BYTE: J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 356 | WrZ80(J.W,OpZ80(R->PC.W++));break; 357 | 358 | case LD_xWORD_HL: 359 | J.B.l=OpZ80(R->PC.W++); 360 | J.B.h=OpZ80(R->PC.W++); 361 | WrZ80(J.W++,R->XX.B.l); 362 | WrZ80(J.W,R->XX.B.h); 363 | break; 364 | 365 | case LD_HL_xWORD: 366 | J.B.l=OpZ80(R->PC.W++); 367 | J.B.h=OpZ80(R->PC.W++); 368 | R->XX.B.l=RdZ80(J.W++); 369 | R->XX.B.h=RdZ80(J.W); 370 | break; 371 | 372 | case LD_A_xWORD: 373 | J.B.l=OpZ80(R->PC.W++); 374 | J.B.h=OpZ80(R->PC.W++); 375 | R->AF.B.h=RdZ80(J.W); 376 | break; 377 | 378 | case LD_xWORD_A: 379 | J.B.l=OpZ80(R->PC.W++); 380 | J.B.h=OpZ80(R->PC.W++); 381 | WrZ80(J.W,R->AF.B.h); 382 | break; 383 | 384 | case EX_HL_xSP: 385 | J.B.l=RdZ80(R->SPtr.W);WrZ80(R->SPtr.W++,R->XX.B.l); 386 | J.B.h=RdZ80(R->SPtr.W);WrZ80(R->SPtr.W--,R->XX.B.h); 387 | R->XX.W=J.W; 388 | break; 389 | 390 | case DAA: 391 | J.W=R->AF.B.h; 392 | if(R->AF.B.l&C_FLAG) J.W|=256; 393 | if(R->AF.B.l&H_FLAG) J.W|=512; 394 | if(R->AF.B.l&N_FLAG) J.W|=1024; 395 | R->AF.W=DAATable[J.W]; 396 | break; 397 | -------------------------------------------------------------------------------- /src/Tables.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** Tables.h **/ 4 | /** **/ 5 | /** This file contains tables of used by Z80 emulation to **/ 6 | /** compute SIGN,ZERO, PARITY flags, and decimal correction **/ 7 | /** There are also timing tables for Z80 opcodes. This file **/ 8 | /** is included from Z80.c. **/ 9 | /** **/ 10 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 11 | /** You are not allowed to distribute this software **/ 12 | /** commercially. Please, notify me, if you make any **/ 13 | /** changes to this file. **/ 14 | /*************************************************************/ 15 | 16 | static const byte Cycles[256] = 17 | { 18 | 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, 19 | 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, 20 | 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, 21 | 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, 22 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, 23 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, 24 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, 25 | 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, 26 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, 27 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, 28 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, 29 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, 30 | 5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11, 31 | 5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11, 32 | 5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11, 33 | 5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11 34 | }; 35 | 36 | static const byte CyclesCB[256] = 37 | { 38 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 39 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 40 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 41 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 42 | 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, 43 | 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, 44 | 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, 45 | 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, 46 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 47 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 48 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 49 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 50 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 51 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 52 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 53 | 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8 54 | }; 55 | 56 | static const byte CyclesED[256] = 57 | { 58 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62 | 12,12,15,20, 8,14, 8, 9,12,12,15,20, 0,14, 0, 9, 63 | 12,12,15,20, 0, 0, 8, 9,12,12,15,20, 0, 0, 8, 9, 64 | 12,12,15,20, 0, 0, 0,18,12,12,15,20, 0, 0, 0,18, 65 | 12, 0,15,20, 0, 0, 0, 0,12,12,15,20, 0, 0, 0, 0, 66 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68 | 16,16,16,16, 0, 0, 0, 0,16,16,16,16, 0, 0, 0, 0, 69 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 74 | }; 75 | 76 | static const byte CyclesXX[256] = 77 | { 78 | 0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0, 79 | 0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0, 80 | 0,14,20,10, 9, 9, 9, 0, 0,15,20,10, 9, 9, 9, 0, 81 | 0, 0, 0, 0,23,23,19, 0, 0,15, 0, 0, 0, 0, 0, 0, 82 | 0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0, 83 | 0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0, 84 | 9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9, 85 | 19,19,19,19,19,19,19,19, 0, 0, 0, 0, 9, 9,19, 0, 86 | 0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0, 87 | 0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0, 88 | 0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0, 89 | 0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0, 90 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92 | 0,14, 0,23, 0,15, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 93 | 0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0, 0, 0, 0, 0 94 | }; 95 | 96 | static const byte CyclesXXCB[256] = 97 | { 98 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 99 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 100 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 101 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 102 | 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 103 | 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 104 | 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 105 | 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 106 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 107 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 108 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 109 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 110 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 111 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 112 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0, 113 | 0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0 114 | }; 115 | 116 | static const byte ZSTable[256] = 117 | { 118 | Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 119 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 120 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 121 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 122 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 123 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 124 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 125 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 126 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 127 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 128 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 129 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 130 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 131 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 132 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 133 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 134 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 135 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 136 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 137 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 138 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 139 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 140 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG, 141 | S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG 142 | }; 143 | 144 | static const byte PZSTable[256] = 145 | { 146 | Z_FLAG|P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0, 147 | 0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG, 148 | 0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0, 149 | 0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0, 150 | P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG, 151 | 0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0, 152 | P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG, 153 | P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG, 154 | 0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0, 155 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 156 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 157 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 158 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 159 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 160 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 161 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 162 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 163 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 164 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 165 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 166 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 167 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 168 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 169 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 170 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 171 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 172 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 173 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 174 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 175 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 176 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 177 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 178 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 179 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 180 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 181 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 182 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 183 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG, 184 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 185 | S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG, 186 | S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG 187 | }; 188 | 189 | static const zword DAATable[2048] = 190 | { 191 | 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, 192 | 0x0808,0x090C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510, 193 | 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, 194 | 0x180C,0x1908,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530, 195 | 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, 196 | 0x282C,0x2928,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534, 197 | 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, 198 | 0x3828,0x392C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510, 199 | 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, 200 | 0x480C,0x4908,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514, 201 | 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, 202 | 0x5808,0x590C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534, 203 | 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, 204 | 0x6828,0x692C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530, 205 | 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, 206 | 0x782C,0x7928,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590, 207 | 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, 208 | 0x888C,0x8988,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594, 209 | 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, 210 | 0x9888,0x998C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515, 211 | 0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701, 212 | 0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511, 213 | 0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705, 214 | 0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531, 215 | 0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725, 216 | 0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535, 217 | 0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721, 218 | 0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511, 219 | 0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705, 220 | 0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515, 221 | 0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701, 222 | 0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535, 223 | 0x6025,0x6121,0x6221,0x6325,0x6421,0x6525,0x6625,0x6721, 224 | 0x6829,0x692D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531, 225 | 0x7021,0x7125,0x7225,0x7321,0x7425,0x7521,0x7621,0x7725, 226 | 0x782D,0x7929,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591, 227 | 0x8081,0x8185,0x8285,0x8381,0x8485,0x8581,0x8681,0x8785, 228 | 0x888D,0x8989,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595, 229 | 0x9085,0x9181,0x9281,0x9385,0x9481,0x9585,0x9685,0x9781, 230 | 0x9889,0x998D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5, 231 | 0xA0A5,0xA1A1,0xA2A1,0xA3A5,0xA4A1,0xA5A5,0xA6A5,0xA7A1, 232 | 0xA8A9,0xA9AD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1, 233 | 0xB0A1,0xB1A5,0xB2A5,0xB3A1,0xB4A5,0xB5A1,0xB6A1,0xB7A5, 234 | 0xB8AD,0xB9A9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595, 235 | 0xC085,0xC181,0xC281,0xC385,0xC481,0xC585,0xC685,0xC781, 236 | 0xC889,0xC98D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591, 237 | 0xD081,0xD185,0xD285,0xD381,0xD485,0xD581,0xD681,0xD785, 238 | 0xD88D,0xD989,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1, 239 | 0xE0A1,0xE1A5,0xE2A5,0xE3A1,0xE4A5,0xE5A1,0xE6A1,0xE7A5, 240 | 0xE8AD,0xE9A9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5, 241 | 0xF0A5,0xF1A1,0xF2A1,0xF3A5,0xF4A1,0xF5A5,0xF6A5,0xF7A1, 242 | 0xF8A9,0xF9AD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515, 243 | 0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701, 244 | 0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511, 245 | 0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705, 246 | 0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531, 247 | 0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725, 248 | 0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535, 249 | 0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721, 250 | 0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511, 251 | 0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705, 252 | 0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515, 253 | 0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701, 254 | 0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535, 255 | 0x0604,0x0700,0x0808,0x090C,0x0A0C,0x0B08,0x0C0C,0x0D08, 256 | 0x0E08,0x0F0C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510, 257 | 0x1600,0x1704,0x180C,0x1908,0x1A08,0x1B0C,0x1C08,0x1D0C, 258 | 0x1E0C,0x1F08,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530, 259 | 0x2620,0x2724,0x282C,0x2928,0x2A28,0x2B2C,0x2C28,0x2D2C, 260 | 0x2E2C,0x2F28,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534, 261 | 0x3624,0x3720,0x3828,0x392C,0x3A2C,0x3B28,0x3C2C,0x3D28, 262 | 0x3E28,0x3F2C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510, 263 | 0x4600,0x4704,0x480C,0x4908,0x4A08,0x4B0C,0x4C08,0x4D0C, 264 | 0x4E0C,0x4F08,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514, 265 | 0x5604,0x5700,0x5808,0x590C,0x5A0C,0x5B08,0x5C0C,0x5D08, 266 | 0x5E08,0x5F0C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534, 267 | 0x6624,0x6720,0x6828,0x692C,0x6A2C,0x6B28,0x6C2C,0x6D28, 268 | 0x6E28,0x6F2C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530, 269 | 0x7620,0x7724,0x782C,0x7928,0x7A28,0x7B2C,0x7C28,0x7D2C, 270 | 0x7E2C,0x7F28,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590, 271 | 0x8680,0x8784,0x888C,0x8988,0x8A88,0x8B8C,0x8C88,0x8D8C, 272 | 0x8E8C,0x8F88,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594, 273 | 0x9684,0x9780,0x9888,0x998C,0x9A8C,0x9B88,0x9C8C,0x9D88, 274 | 0x9E88,0x9F8C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515, 275 | 0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09, 276 | 0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511, 277 | 0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D, 278 | 0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531, 279 | 0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D, 280 | 0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535, 281 | 0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29, 282 | 0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511, 283 | 0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D, 284 | 0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515, 285 | 0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09, 286 | 0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535, 287 | 0x6625,0x6721,0x6829,0x692D,0x6A2D,0x6B29,0x6C2D,0x6D29, 288 | 0x6E29,0x6F2D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531, 289 | 0x7621,0x7725,0x782D,0x7929,0x7A29,0x7B2D,0x7C29,0x7D2D, 290 | 0x7E2D,0x7F29,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591, 291 | 0x8681,0x8785,0x888D,0x8989,0x8A89,0x8B8D,0x8C89,0x8D8D, 292 | 0x8E8D,0x8F89,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595, 293 | 0x9685,0x9781,0x9889,0x998D,0x9A8D,0x9B89,0x9C8D,0x9D89, 294 | 0x9E89,0x9F8D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5, 295 | 0xA6A5,0xA7A1,0xA8A9,0xA9AD,0xAAAD,0xABA9,0xACAD,0xADA9, 296 | 0xAEA9,0xAFAD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1, 297 | 0xB6A1,0xB7A5,0xB8AD,0xB9A9,0xBAA9,0xBBAD,0xBCA9,0xBDAD, 298 | 0xBEAD,0xBFA9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595, 299 | 0xC685,0xC781,0xC889,0xC98D,0xCA8D,0xCB89,0xCC8D,0xCD89, 300 | 0xCE89,0xCF8D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591, 301 | 0xD681,0xD785,0xD88D,0xD989,0xDA89,0xDB8D,0xDC89,0xDD8D, 302 | 0xDE8D,0xDF89,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1, 303 | 0xE6A1,0xE7A5,0xE8AD,0xE9A9,0xEAA9,0xEBAD,0xECA9,0xEDAD, 304 | 0xEEAD,0xEFA9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5, 305 | 0xF6A5,0xF7A1,0xF8A9,0xF9AD,0xFAAD,0xFBA9,0xFCAD,0xFDA9, 306 | 0xFEA9,0xFFAD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515, 307 | 0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09, 308 | 0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511, 309 | 0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D, 310 | 0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531, 311 | 0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D, 312 | 0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535, 313 | 0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29, 314 | 0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511, 315 | 0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D, 316 | 0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515, 317 | 0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09, 318 | 0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535, 319 | 0x0046,0x0102,0x0202,0x0306,0x0402,0x0506,0x0606,0x0702, 320 | 0x080A,0x090E,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E, 321 | 0x1002,0x1106,0x1206,0x1302,0x1406,0x1502,0x1602,0x1706, 322 | 0x180E,0x190A,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A, 323 | 0x2022,0x2126,0x2226,0x2322,0x2426,0x2522,0x2622,0x2726, 324 | 0x282E,0x292A,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A, 325 | 0x3026,0x3122,0x3222,0x3326,0x3422,0x3526,0x3626,0x3722, 326 | 0x382A,0x392E,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E, 327 | 0x4002,0x4106,0x4206,0x4302,0x4406,0x4502,0x4602,0x4706, 328 | 0x480E,0x490A,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A, 329 | 0x5006,0x5102,0x5202,0x5306,0x5402,0x5506,0x5606,0x5702, 330 | 0x580A,0x590E,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E, 331 | 0x6026,0x6122,0x6222,0x6326,0x6422,0x6526,0x6626,0x6722, 332 | 0x682A,0x692E,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E, 333 | 0x7022,0x7126,0x7226,0x7322,0x7426,0x7522,0x7622,0x7726, 334 | 0x782E,0x792A,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A, 335 | 0x8082,0x8186,0x8286,0x8382,0x8486,0x8582,0x8682,0x8786, 336 | 0x888E,0x898A,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A, 337 | 0x9086,0x9182,0x9282,0x9386,0x9482,0x9586,0x9686,0x9782, 338 | 0x988A,0x998E,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F, 339 | 0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707, 340 | 0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B, 341 | 0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703, 342 | 0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F, 343 | 0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723, 344 | 0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F, 345 | 0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727, 346 | 0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B, 347 | 0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787, 348 | 0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B, 349 | 0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783, 350 | 0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F, 351 | 0xA0A7,0xA1A3,0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3, 352 | 0xA8AB,0xA9AF,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF, 353 | 0xB0A3,0xB1A7,0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7, 354 | 0xB8AF,0xB9AB,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB, 355 | 0xC087,0xC183,0xC283,0xC387,0xC483,0xC587,0xC687,0xC783, 356 | 0xC88B,0xC98F,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F, 357 | 0xD083,0xD187,0xD287,0xD383,0xD487,0xD583,0xD683,0xD787, 358 | 0xD88F,0xD98B,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B, 359 | 0xE0A3,0xE1A7,0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7, 360 | 0xE8AF,0xE9AB,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB, 361 | 0xF0A7,0xF1A3,0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3, 362 | 0xF8AB,0xF9AF,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF, 363 | 0x0047,0x0103,0x0203,0x0307,0x0403,0x0507,0x0607,0x0703, 364 | 0x080B,0x090F,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F, 365 | 0x1003,0x1107,0x1207,0x1303,0x1407,0x1503,0x1603,0x1707, 366 | 0x180F,0x190B,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B, 367 | 0x2023,0x2127,0x2227,0x2323,0x2427,0x2523,0x2623,0x2727, 368 | 0x282F,0x292B,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B, 369 | 0x3027,0x3123,0x3223,0x3327,0x3423,0x3527,0x3627,0x3723, 370 | 0x382B,0x392F,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F, 371 | 0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707, 372 | 0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B, 373 | 0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703, 374 | 0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F, 375 | 0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723, 376 | 0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F, 377 | 0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727, 378 | 0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B, 379 | 0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787, 380 | 0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B, 381 | 0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783, 382 | 0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F, 383 | 0xFABE,0xFBBA,0xFCBE,0xFDBA,0xFEBA,0xFFBE,0x0046,0x0102, 384 | 0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E, 385 | 0x0A1E,0x0B1A,0x0C1E,0x0D1A,0x0E1A,0x0F1E,0x1002,0x1106, 386 | 0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A, 387 | 0x1A1A,0x1B1E,0x1C1A,0x1D1E,0x1E1E,0x1F1A,0x2022,0x2126, 388 | 0x2226,0x2322,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A, 389 | 0x2A3A,0x2B3E,0x2C3A,0x2D3E,0x2E3E,0x2F3A,0x3026,0x3122, 390 | 0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E, 391 | 0x3A3E,0x3B3A,0x3C3E,0x3D3A,0x3E3A,0x3F3E,0x4002,0x4106, 392 | 0x4206,0x4302,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A, 393 | 0x4A1A,0x4B1E,0x4C1A,0x4D1E,0x4E1E,0x4F1A,0x5006,0x5102, 394 | 0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E, 395 | 0x5A1E,0x5B1A,0x5C1E,0x5D1A,0x5E1A,0x5F1E,0x6026,0x6122, 396 | 0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E, 397 | 0x6A3E,0x6B3A,0x6C3E,0x6D3A,0x6E3A,0x6F3E,0x7022,0x7126, 398 | 0x7226,0x7322,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A, 399 | 0x7A3A,0x7B3E,0x7C3A,0x7D3E,0x7E3E,0x7F3A,0x8082,0x8186, 400 | 0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A, 401 | 0x8A9A,0x8B9E,0x8C9A,0x8D9E,0x8E9E,0x8F9A,0x9086,0x9182, 402 | 0x9282,0x9386,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F, 403 | 0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107, 404 | 0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B, 405 | 0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103, 406 | 0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F, 407 | 0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123, 408 | 0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F, 409 | 0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127, 410 | 0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B, 411 | 0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187, 412 | 0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B, 413 | 0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183, 414 | 0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F, 415 | 0x9A9F,0x9B9B,0x9C9F,0x9D9B,0x9E9B,0x9F9F,0xA0A7,0xA1A3, 416 | 0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF, 417 | 0xAABF,0xABBB,0xACBF,0xADBB,0xAEBB,0xAFBF,0xB0A3,0xB1A7, 418 | 0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB, 419 | 0xBABB,0xBBBF,0xBCBB,0xBDBF,0xBEBF,0xBFBB,0xC087,0xC183, 420 | 0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F, 421 | 0xCA9F,0xCB9B,0xCC9F,0xCD9B,0xCE9B,0xCF9F,0xD083,0xD187, 422 | 0xD287,0xD383,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B, 423 | 0xDA9B,0xDB9F,0xDC9B,0xDD9F,0xDE9F,0xDF9B,0xE0A3,0xE1A7, 424 | 0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB, 425 | 0xEABB,0xEBBF,0xECBB,0xEDBF,0xEEBF,0xEFBB,0xF0A7,0xF1A3, 426 | 0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF, 427 | 0xFABF,0xFBBB,0xFCBF,0xFDBB,0xFEBB,0xFFBF,0x0047,0x0103, 428 | 0x0203,0x0307,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F, 429 | 0x0A1F,0x0B1B,0x0C1F,0x0D1B,0x0E1B,0x0F1F,0x1003,0x1107, 430 | 0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B, 431 | 0x1A1B,0x1B1F,0x1C1B,0x1D1F,0x1E1F,0x1F1B,0x2023,0x2127, 432 | 0x2227,0x2323,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B, 433 | 0x2A3B,0x2B3F,0x2C3B,0x2D3F,0x2E3F,0x2F3B,0x3027,0x3123, 434 | 0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F, 435 | 0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107, 436 | 0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B, 437 | 0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103, 438 | 0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F, 439 | 0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123, 440 | 0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F, 441 | 0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127, 442 | 0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B, 443 | 0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187, 444 | 0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B, 445 | 0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183, 446 | 0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F 447 | }; 448 | -------------------------------------------------------------------------------- /src/Z80.c: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** Z80.c **/ 4 | /** **/ 5 | /** This file contains implementation for Z80 CPU. Don't **/ 6 | /** forget to provide RdZ80(), WrZ80(), InZ80(), OutZ80(), **/ 7 | /** LoopZ80(), and PatchZ80() functions to accomodate the **/ 8 | /** emulated machine's architecture. **/ 9 | /** **/ 10 | /** Copyright (C) Marat Fayzullin 1994-2007 **/ 11 | /** You are not allowed to distribute this software **/ 12 | /** commercially. Please, notify me, if you make any **/ 13 | /** changes to this file. **/ 14 | /*************************************************************/ 15 | 16 | #include "Z80.h" 17 | #include "Tables.h" 18 | #include 19 | 20 | /** INLINE ***************************************************/ 21 | /** C99 standard has "inline", but older compilers used **/ 22 | /** __inline for the same purpose. **/ 23 | /*************************************************************/ 24 | #ifdef __C99__ 25 | #define INLINE static inline 26 | #else 27 | #define INLINE static __inline 28 | #endif 29 | 30 | /** System-Dependent Stuff ***********************************/ 31 | /** This is system-dependent code put here to speed things **/ 32 | /** up. It has to stay inlined to be fast. **/ 33 | /*************************************************************/ 34 | #ifdef COLEM 35 | #define RdZ80 RDZ80 36 | extern byte *ROMPage[]; 37 | INLINE byte RdZ80(zword A) { return(ROMPage[A>>13][A&0x1FFF]); } 38 | #endif 39 | 40 | #ifdef SPECCY 41 | #define RdZ80 RDZ80 42 | #define WrZ80 WRZ80 43 | extern byte *Page[],*ROM; 44 | INLINE byte RdZ80(zword A) { return(Page[A>>13][A&0x1FFF]); } 45 | INLINE void WrZ80(zword A,byte V) { if(Page[A>>13]>13][A&0x1FFF]=V; } 46 | #endif 47 | 48 | #ifdef MG 49 | #define RdZ80 RDZ80 50 | extern byte *Page[]; 51 | INLINE byte RdZ80(zword A) { return(Page[A>>13][A&0x1FFF]); } 52 | #endif 53 | 54 | #ifdef FMSX 55 | #define FAST_RDOP 56 | extern byte *RAM[]; 57 | INLINE byte OpZ80(zword A) { return(RAM[A>>13][A&0x1FFF]); } 58 | #endif 59 | 60 | /** FAST_RDOP ************************************************/ 61 | /** With this #define not present, RdZ80() should perform **/ 62 | /** the functions of OpZ80(). **/ 63 | /*************************************************************/ 64 | #ifndef FAST_RDOP 65 | #define OpZ80(A) RdZ80(A) 66 | #endif 67 | 68 | #define S(Fl) R->AF.B.l|=Fl 69 | #define R(Fl) R->AF.B.l&=~(Fl) 70 | #define FLAGS(Rg,Fl) R->AF.B.l=Fl|ZSTable[Rg] 71 | 72 | #define M_RLC(Rg) \ 73 | R->AF.B.l=Rg>>7;Rg=(Rg<<1)|R->AF.B.l;R->AF.B.l|=PZSTable[Rg] 74 | #define M_RRC(Rg) \ 75 | R->AF.B.l=Rg&0x01;Rg=(Rg>>1)|(R->AF.B.l<<7);R->AF.B.l|=PZSTable[Rg] 76 | #define M_RL(Rg) \ 77 | if(Rg&0x80) \ 78 | { \ 79 | Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \ 80 | R->AF.B.l=PZSTable[Rg]|C_FLAG; \ 81 | } \ 82 | else \ 83 | { \ 84 | Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \ 85 | R->AF.B.l=PZSTable[Rg]; \ 86 | } 87 | #define M_RR(Rg) \ 88 | if(Rg&0x01) \ 89 | { \ 90 | Rg=(Rg>>1)|(R->AF.B.l<<7); \ 91 | R->AF.B.l=PZSTable[Rg]|C_FLAG; \ 92 | } \ 93 | else \ 94 | { \ 95 | Rg=(Rg>>1)|(R->AF.B.l<<7); \ 96 | R->AF.B.l=PZSTable[Rg]; \ 97 | } 98 | 99 | #define M_SLA(Rg) \ 100 | R->AF.B.l=Rg>>7;Rg<<=1;R->AF.B.l|=PZSTable[Rg] 101 | #define M_SRA(Rg) \ 102 | R->AF.B.l=Rg&C_FLAG;Rg=(Rg>>1)|(Rg&0x80);R->AF.B.l|=PZSTable[Rg] 103 | 104 | #define M_SLL(Rg) \ 105 | R->AF.B.l=Rg>>7;Rg=(Rg<<1)|0x01;R->AF.B.l|=PZSTable[Rg] 106 | #define M_SRL(Rg) \ 107 | R->AF.B.l=Rg&0x01;Rg>>=1;R->AF.B.l|=PZSTable[Rg] 108 | 109 | #define M_BIT(Bit,Rg) \ 110 | R->AF.B.l=(R->AF.B.l&C_FLAG)|H_FLAG|PZSTable[Rg&(1<Rg.B.l=OpZ80(R->SPtr.W++);R->Rg.B.h=OpZ80(R->SPtr.W++) 117 | #define M_PUSH(Rg) \ 118 | WrZ80(--R->SPtr.W,R->Rg.B.h);WrZ80(--R->SPtr.W,R->Rg.B.l) 119 | 120 | #define M_CALL \ 121 | J.B.l=OpZ80(R->PC.W++);J.B.h=OpZ80(R->PC.W++); \ 122 | WrZ80(--R->SPtr.W,R->PC.B.h);WrZ80(--R->SPtr.W,R->PC.B.l); \ 123 | R->PC.W=J.W; \ 124 | JumpZ80(J.W) 125 | 126 | #define M_JP J.B.l=OpZ80(R->PC.W++);J.B.h=OpZ80(R->PC.W);R->PC.W=J.W;JumpZ80(J.W) 127 | #define M_JR R->PC.W+=(offset)OpZ80(R->PC.W)+1;JumpZ80(R->PC.W) 128 | #define M_RET R->PC.B.l=OpZ80(R->SPtr.W++);R->PC.B.h=OpZ80(R->SPtr.W++);JumpZ80(R->PC.W) 129 | 130 | #define M_RST(Ad) \ 131 | WrZ80(--R->SPtr.W,R->PC.B.h);WrZ80(--R->SPtr.W,R->PC.B.l);R->PC.W=Ad;JumpZ80(Ad) 132 | 133 | #define M_LDWORD(Rg) \ 134 | R->Rg.B.l=OpZ80(R->PC.W++);R->Rg.B.h=OpZ80(R->PC.W++) 135 | 136 | #define M_ADD(Rg) \ 137 | J.W=R->AF.B.h+Rg; \ 138 | R->AF.B.l= \ 139 | (~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \ 140 | J.B.h|ZSTable[J.B.l]| \ 141 | ((R->AF.B.h^Rg^J.B.l)&H_FLAG); \ 142 | R->AF.B.h=J.B.l 143 | 144 | #define M_SUB(Rg) \ 145 | J.W=R->AF.B.h-Rg; \ 146 | R->AF.B.l= \ 147 | ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \ 148 | N_FLAG|-J.B.h|ZSTable[J.B.l]| \ 149 | ((R->AF.B.h^Rg^J.B.l)&H_FLAG); \ 150 | R->AF.B.h=J.B.l 151 | 152 | #define M_ADC(Rg) \ 153 | J.W=R->AF.B.h+Rg+(R->AF.B.l&C_FLAG); \ 154 | R->AF.B.l= \ 155 | (~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \ 156 | J.B.h|ZSTable[J.B.l]| \ 157 | ((R->AF.B.h^Rg^J.B.l)&H_FLAG); \ 158 | R->AF.B.h=J.B.l 159 | 160 | #define M_SBC(Rg) \ 161 | J.W=R->AF.B.h-Rg-(R->AF.B.l&C_FLAG); \ 162 | R->AF.B.l= \ 163 | ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \ 164 | N_FLAG|-J.B.h|ZSTable[J.B.l]| \ 165 | ((R->AF.B.h^Rg^J.B.l)&H_FLAG); \ 166 | R->AF.B.h=J.B.l 167 | 168 | #define M_CP(Rg) \ 169 | J.W=R->AF.B.h-Rg; \ 170 | R->AF.B.l= \ 171 | ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \ 172 | N_FLAG|-J.B.h|ZSTable[J.B.l]| \ 173 | ((R->AF.B.h^Rg^J.B.l)&H_FLAG) 174 | 175 | #define M_AND(Rg) R->AF.B.h&=Rg;R->AF.B.l=H_FLAG|PZSTable[R->AF.B.h] 176 | #define M_OR(Rg) R->AF.B.h|=Rg;R->AF.B.l=PZSTable[R->AF.B.h] 177 | #define M_XOR(Rg) R->AF.B.h^=Rg;R->AF.B.l=PZSTable[R->AF.B.h] 178 | 179 | #define M_IN(Rg) \ 180 | Rg=InZ80(R->BC.W); \ 181 | R->AF.B.l=PZSTable[Rg]|(R->AF.B.l&C_FLAG) 182 | 183 | #define M_INC(Rg) \ 184 | Rg++; \ 185 | R->AF.B.l= \ 186 | (R->AF.B.l&C_FLAG)|ZSTable[Rg]| \ 187 | (Rg==0x80? V_FLAG:0)|(Rg&0x0F? 0:H_FLAG) 188 | 189 | #define M_DEC(Rg) \ 190 | Rg--; \ 191 | R->AF.B.l= \ 192 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \ 193 | (Rg==0x7F? V_FLAG:0)|((Rg&0x0F)==0x0F? H_FLAG:0) 194 | 195 | #define M_ADDW(Rg1,Rg2) \ 196 | J.W=(R->Rg1.W+R->Rg2.W)&0xFFFF; \ 197 | R->AF.B.l= \ 198 | (R->AF.B.l&~(H_FLAG|N_FLAG|C_FLAG))| \ 199 | ((R->Rg1.W^R->Rg2.W^J.W)&0x1000? H_FLAG:0)| \ 200 | (((long)R->Rg1.W+(long)R->Rg2.W)&0x10000? C_FLAG:0); \ 201 | R->Rg1.W=J.W 202 | 203 | #define M_ADCW(Rg) \ 204 | I=R->AF.B.l&C_FLAG;J.W=(R->HL.W+R->Rg.W+I)&0xFFFF; \ 205 | R->AF.B.l= \ 206 | (((long)R->HL.W+(long)R->Rg.W+(long)I)&0x10000? C_FLAG:0)| \ 207 | (~(R->HL.W^R->Rg.W)&(R->Rg.W^J.W)&0x8000? V_FLAG:0)| \ 208 | ((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \ 209 | (J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \ 210 | R->HL.W=J.W 211 | 212 | #define M_SBCW(Rg) \ 213 | I=R->AF.B.l&C_FLAG;J.W=(R->HL.W-R->Rg.W-I)&0xFFFF; \ 214 | R->AF.B.l= \ 215 | N_FLAG| \ 216 | (((long)R->HL.W-(long)R->Rg.W-(long)I)&0x10000? C_FLAG:0)| \ 217 | ((R->HL.W^R->Rg.W)&(R->HL.W^J.W)&0x8000? V_FLAG:0)| \ 218 | ((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \ 219 | (J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \ 220 | R->HL.W=J.W 221 | 222 | enum Codes 223 | { 224 | NOP,LD_BC_WORD,LD_xBC_A,INC_BC,INC_B,DEC_B,LD_B_BYTE,RLCA, 225 | EX_AF_AF,ADD_HL_BC,LD_A_xBC,DEC_BC,INC_C,DEC_C,LD_C_BYTE,RRCA, 226 | DJNZ,LD_DE_WORD,LD_xDE_A,INC_DE,INC_D,DEC_D,LD_D_BYTE,RLA, 227 | JR,ADD_HL_DE,LD_A_xDE,DEC_DE,INC_E,DEC_E,LD_E_BYTE,RRA, 228 | JR_NZ,LD_HL_WORD,LD_xWORD_HL,INC_HL,INC_H,DEC_H,LD_H_BYTE,DAA, 229 | JR_Z,ADD_HL_HL,LD_HL_xWORD,DEC_HL,INC_L,DEC_L,LD_L_BYTE,CPL, 230 | JR_NC,LD_SP_WORD,LD_xWORD_A,INC_SP,INC_xHL,DEC_xHL,LD_xHL_BYTE,SCF, 231 | JR_C,ADD_HL_SP,LD_A_xWORD,DEC_SP,INC_A,DEC_A,LD_A_BYTE,CCF, 232 | LD_B_B,LD_B_C,LD_B_D,LD_B_E,LD_B_H,LD_B_L,LD_B_xHL,LD_B_A, 233 | LD_C_B,LD_C_C,LD_C_D,LD_C_E,LD_C_H,LD_C_L,LD_C_xHL,LD_C_A, 234 | LD_D_B,LD_D_C,LD_D_D,LD_D_E,LD_D_H,LD_D_L,LD_D_xHL,LD_D_A, 235 | LD_E_B,LD_E_C,LD_E_D,LD_E_E,LD_E_H,LD_E_L,LD_E_xHL,LD_E_A, 236 | LD_H_B,LD_H_C,LD_H_D,LD_H_E,LD_H_H,LD_H_L,LD_H_xHL,LD_H_A, 237 | LD_L_B,LD_L_C,LD_L_D,LD_L_E,LD_L_H,LD_L_L,LD_L_xHL,LD_L_A, 238 | LD_xHL_B,LD_xHL_C,LD_xHL_D,LD_xHL_E,LD_xHL_H,LD_xHL_L,HALT,LD_xHL_A, 239 | LD_A_B,LD_A_C,LD_A_D,LD_A_E,LD_A_H,LD_A_L,LD_A_xHL,LD_A_A, 240 | ADD_B,ADD_C,ADD_D,ADD_E,ADD_H,ADD_L,ADD_xHL,ADD_A, 241 | ADC_B,ADC_C,ADC_D,ADC_E,ADC_H,ADC_L,ADC_xHL,ADC_A, 242 | SUB_B,SUB_C,SUB_D,SUB_E,SUB_H,SUB_L,SUB_xHL,SUB_A, 243 | SBC_B,SBC_C,SBC_D,SBC_E,SBC_H,SBC_L,SBC_xHL,SBC_A, 244 | AND_B,AND_C,AND_D,AND_E,AND_H,AND_L,AND_xHL,AND_A, 245 | XOR_B,XOR_C,XOR_D,XOR_E,XOR_H,XOR_L,XOR_xHL,XOR_A, 246 | OR_B,OR_C,OR_D,OR_E,OR_H,OR_L,OR_xHL,OR_A, 247 | CP_B,CP_C,CP_D,CP_E,CP_H,CP_L,CP_xHL,CP_A, 248 | RET_NZ,POP_BC,JP_NZ,JP,CALL_NZ,PUSH_BC,ADD_BYTE,RST00, 249 | RET_Z,RET,JP_Z,PFX_CB,CALL_Z,CALL,ADC_BYTE,RST08, 250 | RET_NC,POP_DE,JP_NC,OUTA,CALL_NC,PUSH_DE,SUB_BYTE,RST10, 251 | RET_C,EXX,JP_C,INA,CALL_C,PFX_DD,SBC_BYTE,RST18, 252 | RET_PO,POP_HL,JP_PO,EX_HL_xSP,CALL_PO,PUSH_HL,AND_BYTE,RST20, 253 | RET_PE,LD_PC_HL,JP_PE,EX_DE_HL,CALL_PE,PFX_ED,XOR_BYTE,RST28, 254 | RET_P,POP_AF,JP_P,DI,CALL_P,PUSH_AF,OR_BYTE,RST30, 255 | RET_M,LD_SP_HL,JP_M,EI,CALL_M,PFX_FD,CP_BYTE,RST38 256 | }; 257 | 258 | enum CodesCB 259 | { 260 | RLC_B,RLC_C,RLC_D,RLC_E,RLC_H,RLC_L,RLC_xHL,RLC_A, 261 | RRC_B,RRC_C,RRC_D,RRC_E,RRC_H,RRC_L,RRC_xHL,RRC_A, 262 | RL_B,RL_C,RL_D,RL_E,RL_H,RL_L,RL_xHL,RL_A, 263 | RR_B,RR_C,RR_D,RR_E,RR_H,RR_L,RR_xHL,RR_A, 264 | SLA_B,SLA_C,SLA_D,SLA_E,SLA_H,SLA_L,SLA_xHL,SLA_A, 265 | SRA_B,SRA_C,SRA_D,SRA_E,SRA_H,SRA_L,SRA_xHL,SRA_A, 266 | SLL_B,SLL_C,SLL_D,SLL_E,SLL_H,SLL_L,SLL_xHL,SLL_A, 267 | SRL_B,SRL_C,SRL_D,SRL_E,SRL_H,SRL_L,SRL_xHL,SRL_A, 268 | BIT0_B,BIT0_C,BIT0_D,BIT0_E,BIT0_H,BIT0_L,BIT0_xHL,BIT0_A, 269 | BIT1_B,BIT1_C,BIT1_D,BIT1_E,BIT1_H,BIT1_L,BIT1_xHL,BIT1_A, 270 | BIT2_B,BIT2_C,BIT2_D,BIT2_E,BIT2_H,BIT2_L,BIT2_xHL,BIT2_A, 271 | BIT3_B,BIT3_C,BIT3_D,BIT3_E,BIT3_H,BIT3_L,BIT3_xHL,BIT3_A, 272 | BIT4_B,BIT4_C,BIT4_D,BIT4_E,BIT4_H,BIT4_L,BIT4_xHL,BIT4_A, 273 | BIT5_B,BIT5_C,BIT5_D,BIT5_E,BIT5_H,BIT5_L,BIT5_xHL,BIT5_A, 274 | BIT6_B,BIT6_C,BIT6_D,BIT6_E,BIT6_H,BIT6_L,BIT6_xHL,BIT6_A, 275 | BIT7_B,BIT7_C,BIT7_D,BIT7_E,BIT7_H,BIT7_L,BIT7_xHL,BIT7_A, 276 | RES0_B,RES0_C,RES0_D,RES0_E,RES0_H,RES0_L,RES0_xHL,RES0_A, 277 | RES1_B,RES1_C,RES1_D,RES1_E,RES1_H,RES1_L,RES1_xHL,RES1_A, 278 | RES2_B,RES2_C,RES2_D,RES2_E,RES2_H,RES2_L,RES2_xHL,RES2_A, 279 | RES3_B,RES3_C,RES3_D,RES3_E,RES3_H,RES3_L,RES3_xHL,RES3_A, 280 | RES4_B,RES4_C,RES4_D,RES4_E,RES4_H,RES4_L,RES4_xHL,RES4_A, 281 | RES5_B,RES5_C,RES5_D,RES5_E,RES5_H,RES5_L,RES5_xHL,RES5_A, 282 | RES6_B,RES6_C,RES6_D,RES6_E,RES6_H,RES6_L,RES6_xHL,RES6_A, 283 | RES7_B,RES7_C,RES7_D,RES7_E,RES7_H,RES7_L,RES7_xHL,RES7_A, 284 | SET0_B,SET0_C,SET0_D,SET0_E,SET0_H,SET0_L,SET0_xHL,SET0_A, 285 | SET1_B,SET1_C,SET1_D,SET1_E,SET1_H,SET1_L,SET1_xHL,SET1_A, 286 | SET2_B,SET2_C,SET2_D,SET2_E,SET2_H,SET2_L,SET2_xHL,SET2_A, 287 | SET3_B,SET3_C,SET3_D,SET3_E,SET3_H,SET3_L,SET3_xHL,SET3_A, 288 | SET4_B,SET4_C,SET4_D,SET4_E,SET4_H,SET4_L,SET4_xHL,SET4_A, 289 | SET5_B,SET5_C,SET5_D,SET5_E,SET5_H,SET5_L,SET5_xHL,SET5_A, 290 | SET6_B,SET6_C,SET6_D,SET6_E,SET6_H,SET6_L,SET6_xHL,SET6_A, 291 | SET7_B,SET7_C,SET7_D,SET7_E,SET7_H,SET7_L,SET7_xHL,SET7_A 292 | }; 293 | 294 | enum CodesED 295 | { 296 | DB_00,DB_01,DB_02,DB_03,DB_04,DB_05,DB_06,DB_07, 297 | DB_08,DB_09,DB_0A,DB_0B,DB_0C,DB_0D,DB_0E,DB_0F, 298 | DB_10,DB_11,DB_12,DB_13,DB_14,DB_15,DB_16,DB_17, 299 | DB_18,DB_19,DB_1A,DB_1B,DB_1C,DB_1D,DB_1E,DB_1F, 300 | DB_20,DB_21,DB_22,DB_23,DB_24,DB_25,DB_26,DB_27, 301 | DB_28,DB_29,DB_2A,DB_2B,DB_2C,DB_2D,DB_2E,DB_2F, 302 | DB_30,DB_31,DB_32,DB_33,DB_34,DB_35,DB_36,DB_37, 303 | DB_38,DB_39,DB_3A,DB_3B,DB_3C,DB_3D,DB_3E,DB_3F, 304 | IN_B_xC,OUT_xC_B,SBC_HL_BC,LD_xWORDe_BC,NEG,RETN,IM_0,LD_I_A, 305 | IN_C_xC,OUT_xC_C,ADC_HL_BC,LD_BC_xWORDe,DB_4C,RETI,DB_,LD_R_A, 306 | IN_D_xC,OUT_xC_D,SBC_HL_DE,LD_xWORDe_DE,DB_54,DB_55,IM_1,LD_A_I, 307 | IN_E_xC,OUT_xC_E,ADC_HL_DE,LD_DE_xWORDe,DB_5C,DB_5D,IM_2,LD_A_R, 308 | IN_H_xC,OUT_xC_H,SBC_HL_HL,LD_xWORDe_HL,DB_64,DB_65,DB_66,RRD, 309 | IN_L_xC,OUT_xC_L,ADC_HL_HL,LD_HL_xWORDe,DB_6C,DB_6D,DB_6E,RLD, 310 | IN_F_xC,DB_71,SBC_HL_SP,LD_xWORDe_SP,DB_74,DB_75,DB_76,DB_77, 311 | IN_A_xC,OUT_xC_A,ADC_HL_SP,LD_SP_xWORDe,DB_7C,DB_7D,DB_7E,DB_7F, 312 | DB_80,DB_81,DB_82,DB_83,DB_84,DB_85,DB_86,DB_87, 313 | DB_88,DB_89,DB_8A,DB_8B,DB_8C,DB_8D,DB_8E,DB_8F, 314 | DB_90,DB_91,DB_92,DB_93,DB_94,DB_95,DB_96,DB_97, 315 | DB_98,DB_99,DB_9A,DB_9B,DB_9C,DB_9D,DB_9E,DB_9F, 316 | LDI,CPI,INI,OUTI,DB_A4,DB_A5,DB_A6,DB_A7, 317 | LDD,CPD,IND,OUTD,DB_AC,DB_AD,DB_AE,DB_AF, 318 | LDIR,CPIR,INIR,OTIR,DB_B4,DB_B5,DB_B6,DB_B7, 319 | LDDR,CPDR,INDR,OTDR,DB_BC,DB_BD,DB_BE,DB_BF, 320 | DB_C0,DB_C1,DB_C2,DB_C3,DB_C4,DB_C5,DB_C6,DB_C7, 321 | DB_C8,DB_C9,DB_CA,DB_CB,DB_CC,DB_CD,DB_CE,DB_CF, 322 | DB_D0,DB_D1,DB_D2,DB_D3,DB_D4,DB_D5,DB_D6,DB_D7, 323 | DB_D8,DB_D9,DB_DA,DB_DB,DB_DC,DB_DD,DB_DE,DB_DF, 324 | DB_E0,DB_E1,DB_E2,DB_E3,DB_E4,DB_E5,DB_E6,DB_E7, 325 | DB_E8,DB_E9,DB_EA,DB_EB,DB_EC,DB_ED,DB_EE,DB_EF, 326 | DB_F0,DB_F1,DB_F2,DB_F3,DB_F4,DB_F5,DB_F6,DB_F7, 327 | DB_F8,DB_F9,DB_FA,DB_FB,DB_FC,DB_FD,DB_FE,DB_FF 328 | }; 329 | 330 | static void CodesCB(register Z80 *R) 331 | { 332 | register byte I; 333 | 334 | I=OpZ80(R->PC.W++); 335 | R->ICount-=CyclesCB[I]; 336 | switch(I) 337 | { 338 | #include "CodesCB.h" 339 | default: 340 | if(R->TrapBadOps) 341 | printf 342 | ( 343 | "[Z80 %lX] Unrecognized instruction: CB %02X at PC=%04X\n", 344 | (long)(R->User),OpZ80(R->PC.W-1),R->PC.W-2 345 | ); 346 | } 347 | } 348 | 349 | static void CodesDDCB(register Z80 *R) 350 | { 351 | register pair J; 352 | register byte I; 353 | 354 | #define XX IX 355 | J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 356 | I=OpZ80(R->PC.W++); 357 | R->ICount-=CyclesXXCB[I]; 358 | switch(I) 359 | { 360 | #include "CodesXCB.h" 361 | default: 362 | if(R->TrapBadOps) 363 | printf 364 | ( 365 | "[Z80 %lX] Unrecognized instruction: DD CB %02X %02X at PC=%04X\n", 366 | (long)(R->User),OpZ80(R->PC.W-2),OpZ80(R->PC.W-1),R->PC.W-4 367 | ); 368 | } 369 | #undef XX 370 | } 371 | 372 | static void CodesFDCB(register Z80 *R) 373 | { 374 | register pair J; 375 | register byte I; 376 | 377 | #define XX IY 378 | J.W=R->XX.W+(offset)OpZ80(R->PC.W++); 379 | I=OpZ80(R->PC.W++); 380 | R->ICount-=CyclesXXCB[I]; 381 | switch(I) 382 | { 383 | #include "CodesXCB.h" 384 | default: 385 | if(R->TrapBadOps) 386 | printf 387 | ( 388 | "[Z80 %lX] Unrecognized instruction: FD CB %02X %02X at PC=%04X\n", 389 | (long)R->User,OpZ80(R->PC.W-2),OpZ80(R->PC.W-1),R->PC.W-4 390 | ); 391 | } 392 | #undef XX 393 | } 394 | 395 | static void CodesED(register Z80 *R) 396 | { 397 | register byte I; 398 | register pair J; 399 | 400 | I=OpZ80(R->PC.W++); 401 | R->ICount-=CyclesED[I]; 402 | switch(I) 403 | { 404 | #include "CodesED.h" 405 | case PFX_ED: 406 | R->PC.W--;break; 407 | default: 408 | if(R->TrapBadOps) 409 | printf 410 | ( 411 | "[Z80 %lX] Unrecognized instruction: ED %02X at PC=%04X\n", 412 | (long)R->User,OpZ80(R->PC.W-1),R->PC.W-2 413 | ); 414 | } 415 | } 416 | 417 | static void CodesDD(register Z80 *R) 418 | { 419 | register byte I; 420 | register pair J; 421 | 422 | #define XX IX 423 | I=OpZ80(R->PC.W++); 424 | R->ICount-=CyclesXX[I]; 425 | switch(I) 426 | { 427 | #include "CodesXX.h" 428 | case PFX_FD: 429 | case PFX_DD: 430 | R->PC.W--;break; 431 | case PFX_CB: 432 | CodesDDCB(R);break; 433 | default: 434 | if(R->TrapBadOps) 435 | printf 436 | ( 437 | "[Z80 %lX] Unrecognized instruction: DD %02X at PC=%04X\n", 438 | (long)R->User,OpZ80(R->PC.W-1),R->PC.W-2 439 | ); 440 | } 441 | #undef XX 442 | } 443 | 444 | static void CodesFD(register Z80 *R) 445 | { 446 | register byte I; 447 | register pair J; 448 | 449 | #define XX IY 450 | I=OpZ80(R->PC.W++); 451 | R->ICount-=CyclesXX[I]; 452 | switch(I) 453 | { 454 | #include "CodesXX.h" 455 | case PFX_FD: 456 | case PFX_DD: 457 | R->PC.W--;break; 458 | case PFX_CB: 459 | CodesFDCB(R);break; 460 | default: 461 | printf 462 | ( 463 | "Unrecognized instruction: FD %02X at PC=%04X\n", 464 | OpZ80(R->PC.W-1),R->PC.W-2 465 | ); 466 | } 467 | #undef XX 468 | } 469 | 470 | /** ResetZ80() ***********************************************/ 471 | /** This function can be used to reset the register struct **/ 472 | /** before starting execution with Z80(). It sets the **/ 473 | /** registers to their supposed initial values. **/ 474 | /*************************************************************/ 475 | void ResetZ80(Z80 *R) 476 | { 477 | R->PC.W = 0x0000; 478 | R->SPtr.W = 0xF000; 479 | R->AF.W = 0x0000; 480 | R->BC.W = 0x0000; 481 | R->DE.W = 0x0000; 482 | R->HL.W = 0x0000; 483 | R->AF1.W = 0x0000; 484 | R->BC1.W = 0x0000; 485 | R->DE1.W = 0x0000; 486 | R->HL1.W = 0x0000; 487 | R->IX.W = 0x0000; 488 | R->IY.W = 0x0000; 489 | R->I = 0x00; 490 | R->R = 0x00; 491 | R->IFF = 0x00; 492 | R->ICount = R->IPeriod; 493 | R->IRequest = INT_NONE; 494 | R->IBackup = 0; 495 | 496 | JumpZ80(R->PC.W); 497 | } 498 | 499 | /** ExecZ80() ************************************************/ 500 | /** This function will execute given number of Z80 cycles. **/ 501 | /** It will then return the number of cycles left, possibly **/ 502 | /** negative, and current register values in R. **/ 503 | /*************************************************************/ 504 | #ifdef EXECZ80 505 | int ExecZ80(register Z80 *R,register int RunCycles) 506 | { 507 | register byte I; 508 | register pair J; 509 | 510 | for(R->ICount=RunCycles;;) 511 | { 512 | while(R->ICount>0) 513 | { 514 | #ifdef DEBUG 515 | /* Turn tracing on when reached trap address */ 516 | if(R->PC.W==R->Trap) R->Trace=1; 517 | /* Call single-step debugger, exit if requested */ 518 | if(R->Trace) 519 | if(!DebugZ80(R)) return(R->ICount); 520 | #endif 521 | 522 | /* Read opcode and count cycles */ 523 | I=OpZ80(R->PC.W++); 524 | /* Count cycles */ 525 | R->ICount-=Cycles[I]; 526 | 527 | /* Interpret opcode */ 528 | switch(I) 529 | { 530 | #include "Codes.h" 531 | case PFX_CB: CodesCB(R);break; 532 | case PFX_ED: CodesED(R);break; 533 | case PFX_FD: CodesFD(R);break; 534 | case PFX_DD: CodesDD(R);break; 535 | } 536 | } 537 | 538 | /* Unless we have come here after EI, exit */ 539 | if(!(R->IFF&IFF_EI)) return(R->ICount); 540 | else 541 | { 542 | /* Done with AfterEI state */ 543 | R->IFF=(R->IFF&~IFF_EI)|IFF_1; 544 | /* Restore the ICount */ 545 | R->ICount+=R->IBackup-1; 546 | /* Interrupt CPU if needed */ 547 | if((R->IRequest!=INT_NONE)&&(R->IRequest!=INT_QUIT)) IntZ80(R,R->IRequest); 548 | } 549 | } 550 | } 551 | #endif /* EXECZ80 */ 552 | 553 | /** IntZ80() *************************************************/ 554 | /** This function will generate interrupt of given vector. **/ 555 | /*************************************************************/ 556 | void IntZ80(Z80 *R,zword Vector) 557 | { 558 | /* If HALTed, take CPU off HALT instruction */ 559 | if(R->IFF&IFF_HALT) { R->PC.W++;R->IFF&=~IFF_HALT; } 560 | 561 | if((R->IFF&IFF_1)||(Vector==INT_NMI)) 562 | { 563 | /* Save PC on stack */ 564 | M_PUSH(PC); 565 | 566 | /* Automatically reset IRequest if needed */ 567 | if(R->IAutoReset&&(Vector==R->IRequest)) R->IRequest=INT_NONE; 568 | 569 | /* If it is NMI... */ 570 | if(Vector==INT_NMI) 571 | { 572 | /* Clear IFF1 */ 573 | R->IFF&=~(IFF_1|IFF_EI); 574 | /* Jump to hardwired NMI vector */ 575 | R->PC.W=0x0066; 576 | JumpZ80(0x0066); 577 | /* Done */ 578 | return; 579 | } 580 | 581 | /* Further interrupts off */ 582 | R->IFF&=~(IFF_1|IFF_2|IFF_EI); 583 | 584 | /* If in IM2 mode... */ 585 | if(R->IFF&IFF_IM2) 586 | { 587 | /* Make up the vector address */ 588 | Vector=(Vector&0xFF)|((zword)(R->I)<<8); 589 | /* Read the vector */ 590 | R->PC.B.l=RdZ80(Vector++); 591 | R->PC.B.h=RdZ80(Vector); 592 | JumpZ80(R->PC.W); 593 | /* Done */ 594 | return; 595 | } 596 | 597 | /* If in IM1 mode, just jump to hardwired IRQ vector */ 598 | if(R->IFF&IFF_IM1) { R->PC.W=0x0038;JumpZ80(0x0038);return; } 599 | 600 | /* If in IM0 mode... */ 601 | 602 | /* Jump to a vector */ 603 | switch(Vector) 604 | { 605 | case INT_RST00: R->PC.W=0x0000;JumpZ80(0x0000);break; 606 | case INT_RST08: R->PC.W=0x0008;JumpZ80(0x0008);break; 607 | case INT_RST10: R->PC.W=0x0010;JumpZ80(0x0010);break; 608 | case INT_RST18: R->PC.W=0x0018;JumpZ80(0x0018);break; 609 | case INT_RST20: R->PC.W=0x0020;JumpZ80(0x0020);break; 610 | case INT_RST28: R->PC.W=0x0028;JumpZ80(0x0028);break; 611 | case INT_RST30: R->PC.W=0x0030;JumpZ80(0x0030);break; 612 | case INT_RST38: R->PC.W=0x0038;JumpZ80(0x0038);break; 613 | } 614 | } 615 | } 616 | 617 | /** RunZ80() *************************************************/ 618 | /** This function will run Z80 code until an LoopZ80() call **/ 619 | /** returns INT_QUIT. It will return the PC at which **/ 620 | /** emulation stopped, and current register values in R. **/ 621 | /*************************************************************/ 622 | #ifdef RUNZ80 623 | zword RunZ80(Z80 *R) 624 | { 625 | register byte I; 626 | register pair J; 627 | 628 | for(;;) 629 | { 630 | #ifdef DEBUG 631 | /* Turn tracing on when reached trap address */ 632 | if(R->PC.W==R->Trap) R->Trace=1; 633 | /* Call single-step debugger, exit if requested */ 634 | if(R->Trace) 635 | if(!DebugZ80(R)) return(R->PC.W); 636 | #endif 637 | 638 | I=OpZ80(R->PC.W++); 639 | R->ICount-=Cycles[I]; 640 | 641 | switch(I) 642 | { 643 | #include "Codes.h" 644 | case PFX_CB: CodesCB(R);break; 645 | case PFX_ED: CodesED(R);break; 646 | case PFX_FD: CodesFD(R);break; 647 | case PFX_DD: CodesDD(R);break; 648 | } 649 | 650 | /* If cycle counter expired... */ 651 | if(R->ICount<=0) 652 | { 653 | /* If we have come after EI, get address from IRequest */ 654 | /* Otherwise, get it from the loop handler */ 655 | if(R->IFF&IFF_EI) 656 | { 657 | R->IFF=(R->IFF&~IFF_EI)|IFF_1; /* Done with AfterEI state */ 658 | R->ICount+=R->IBackup-1; /* Restore the ICount */ 659 | 660 | /* Call periodic handler or set pending IRQ */ 661 | if(R->ICount>0) J.W=R->IRequest; 662 | else 663 | { 664 | J.W=LoopZ80(R); /* Call periodic handler */ 665 | R->ICount+=R->IPeriod; /* Reset the cycle counter */ 666 | if(J.W==INT_NONE) J.W=R->IRequest; /* Pending IRQ */ 667 | } 668 | } 669 | else 670 | { 671 | J.W=LoopZ80(R); /* Call periodic handler */ 672 | R->ICount+=R->IPeriod; /* Reset the cycle counter */ 673 | if(J.W==INT_NONE) J.W=R->IRequest; /* Pending IRQ */ 674 | } 675 | 676 | if(J.W==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */ 677 | if(J.W!=INT_NONE) IntZ80(R,J.W); /* Int-pt if needed */ 678 | } 679 | } 680 | 681 | /* Execution stopped */ 682 | return(R->PC.W); 683 | } 684 | #endif /* !RUNZ80 */ 685 | 686 | /** StepZ80() ************************************************/ 687 | /** This function will execute a single Z80 opcode. **/ 688 | /** It will return the current register values in R. **/ 689 | /*************************************************************/ 690 | #ifdef STEPZ80 691 | void StepZ80(register Z80 *R) 692 | { 693 | register byte I; 694 | register pair J; 695 | 696 | #ifdef DEBUG 697 | /* Turn tracing on when reached trap address */ 698 | if(R->PC.W==R->Trap) R->Trace=1; 699 | /* Call single-step debugger, exit if requested */ 700 | if(R->Trace) 701 | if(!DebugZ80(R)) return(R->ICount); 702 | #endif 703 | 704 | /* Read opcode and count cycles */ 705 | I=OpZ80(R->PC.W++); 706 | /* Count cycles */ 707 | R->ICount-=Cycles[I]; 708 | 709 | /* Interpret opcode */ 710 | switch(I) 711 | { 712 | #include "Codes.h" 713 | case PFX_CB: CodesCB(R);break; 714 | case PFX_ED: CodesED(R);break; 715 | case PFX_FD: CodesFD(R);break; 716 | case PFX_DD: CodesDD(R);break; 717 | } 718 | 719 | /* Unless we have come here after EI, exit */ 720 | if(!(R->IFF&IFF_EI)) return(R->ICount); 721 | else 722 | { 723 | /* Done with AfterEI state */ 724 | R->IFF=(R->IFF&~IFF_EI)|IFF_1; 725 | /* Restore the ICount */ 726 | R->ICount+=R->IBackup-1; 727 | /* Interrupt CPU if needed */ 728 | if((R->IRequest!=INT_NONE)&&(R->IRequest!=INT_QUIT)) IntZ80(R,R->IRequest); 729 | } 730 | } 731 | #endif /* STEPZ80 */ 732 | --------------------------------------------------------------------------------