diff --git a/.circleci/config.yml b/.circleci/config.yml index 2e960fb3..6c340d08 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: - checkout - run: name: "Install Prerequests" - command: "sudo apt-get install -y clang clang-format g++-10" + command: "sudo apt-get install -y clang g++-10" - run: name: "Build and Test Z80 Emulator" command: "make ci" diff --git a/CHANGELOG.md b/CHANGELOG.md index 659ac44f..23e426a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Change log +## Version 1.8.0 (Oct 23, 2022 JST) + +- Make strict the registers conditions at callback time (NOTE: **Destructive** change specification) + - see the details: https://github.com/suzukiplan/z80/issues/49 +- When a runtime error occurs, such as executing an instruction that not exists, a crash used to occur, but now it throws a `std::runtime_error` exception. +- add new FP methods: + - `addBreakPointFP` + - `addBreakOperandFP` + - `addReturnHandlerFP` + - `addCallHandlerFP` +- add new setCallback methods: + - `setupMemoryCallback` (split from setupCallback) + - `setupDeviceCallback` (split from setupCallback) + - `setupMemoryCallbackFP` (split from setupCallbackFP) + - `setupDeviceCallbackFP` (split from setupCallbackFP) +- Implicit call the callback setter methods (`with FP`), when a function pointer that is not template is explicitly specified when a callback setter methods (`without FP`) was called. + ## Version 1.7.1 (Oct 18, 2022, JST) - A bug that prevented `addBreakOperand` from working as expected has been addressed. diff --git a/README.md b/README.md index 44dcdc5f..94284c8e 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ void outPort(void* arg, unsigned short port, unsigned char value) Note that by default, only the lower 8 bits of the port number can be obtained in the callback argument, and the upper 8 bits must be referenced from register B. -If you want to get it in 16 bits from the beginning, please initialize with 6th argument to `true` as follows: +If you want to get it in 16 bits from the beginning, please initialize with `returnPortAs16Bits` (6th argument) to `true` as follows: ```c++ Z80 z80(&mmu, readByte, writeByte, inPort, outPort, true); @@ -122,23 +122,24 @@ Normally, `std::function` is used for callbacks, but in more performance-sensiti ```c++ Z80 z80(&mmu); - z80.setupCallbackFP([](void* arg, unsigned short addr) { - return 0x00; // read procedure - }, [](void* arg, unsigned char addr, unsigned char value) { - // write procedure - }, [](void* arg, unsigned short port) { - return 0x00; // input port procedure - }, [](void* arg, unsigned short port, unsigned char value) { - // output port procedure - }); + z80.setupCallbackFP(readByte, writeByte, inPort, outPort); ``` However, using function pointers causes inconveniences such as the inability to specify a capture in a lambda expression. In most cases, optimization with the `-O2` option will not cause performance problems, but in case environments where more severe performance is required, `setupCallbackFP` is recommended. -The following article (in Japanese) provides a performance comparison between function pointers and `std::function`: - -https://qiita.com/suzukiplan/items/e459bf47f6c659acc74d +> The following article (in Japanese) provides a performance comparison between function pointers and `std::function`: +> +> https://qiita.com/suzukiplan/items/e459bf47f6c659acc74d +> +> The above article gives an example of the time it took to execute 100 million times call of function-pointer and three patterns of `std::function` calls (`bind`, `direct`, `lambda`) as following: +> +> |Optimization Option|function pointer|`bind`|`direct`|`lambda`| +> |:-:|-:|-:|-:|-:| +> |none|228,894μs|6,459,751μs|2,958,097μs|2,782,300μs| +> |-O|191,496μs|2,482,582μs|960868μs|668010μs| +> |-O2|100,359μs|287,467μs|313,414μs|222,633μs| +> |-Ofast|91,904μs|27,9341μs|285,927μs|188,635μs| ### 4. Execute @@ -147,6 +148,82 @@ https://qiita.com/suzukiplan/items/e459bf47f6c659acc74d int actualExecuteClocks = z80.execute(1234); ``` +#### 4-1. Actual execute clocks + +- The `execute` method repeats the execution of an instruction until the total number of clocks from the time of the call is greater than or equal to the value specified in the "clocks" argument. +- If a value less than or equal to 0 is specified, no instruction is executed at all. +- If you want single operand execution, you can specify 1. + +#### 4-2. Interruption of execution + +Execution of the `requestBreak` method can abort the `execute` at an arbitrary time. + +> A typical 8-bit game console emulator implementation that I envision: +> +> - Implement synchronization with Video Display Processor (VDP) and other devices (sound modules, etc.) in `consumeClock` callback. +> - Call `requestBreak` when V-SYNC signal is received from VDP. +> - Call `execute` with a large value such as `INT_MAX`. + +#### 4-3. Example + +Code: [test/test-execute.cpp](test/test-execute.cpp) + +```c++ +#include "z80.hpp" + +int main() +{ + unsigned char rom[256] = { + 0x01, 0x34, 0x12, // LD BC, $1234 + 0x3E, 0x01, // LD A, $01 + 0xED, 0x79, // OUT (C), A + 0xED, 0x78, // IN A, (C) + 0xc3, 0x09, 0x00, // JMP $0009 + }; + Z80 z80([=](void* arg, unsigned short addr) { return rom[addr & 0xFF]; }, + [](void* arg, unsigned short addr, unsigned char value) {}, + [](void* arg, unsigned short port) { return 0x00; }, + [](void* arg, unsigned short port, unsigned char value) { + // request break the execute function after output port operand has executed. + ((Z80*)arg)->requestBreak(); + }, &z80); + z80.setDebugMessage([](void* arg, const char* msg) { puts(msg); }); + z80.setConsumeClockCallback([](void* arg, int clocks) { printf("consume %dHz\n", clocks); }); + puts("===== execute(0) ====="); + printf("actualExecuteClocks = %dHz\n", z80.execute(0)); + puts("===== execute(1) ====="); + printf("actualExecuteClocks = %dHz\n", z80.execute(1)); + puts("===== execute(0x7FFFFFFF) ====="); + printf("actualExecuteClocks = %dHz\n", z80.execute(0x7FFFFFFF)); + return 0; +} +``` + +Result is following: + +``` +===== execute(0) ===== +actualExecuteClocks = 0Hz ... 0 is specified, no instruction is executed at all +===== execute(1) ===== +consume 2Hz +consume 2Hz +consume 3Hz +consume 3Hz +[0000] LD BC<$0000>, $1234 +actualExecuteClocks = 10Hz ... specify 1 to single step execution +===== execute(0x7FFFFFFF) ===== +consume 2Hz +consume 2Hz +consume 3Hz +[0003] LD A<$FF>, $01 +consume 2Hz +consume 2Hz +consume 4Hz +[0005] OUT (C<$34>), A<$01> +consume 4Hz +actualExecuteClocks = 19Hz ... 2147483647Hz+ is not executed but interrupted after completion of OUT due to requestBreak during OUT execution +``` + ### 5. Generate interrupt #### IRQ; Interrupt Request @@ -193,8 +270,9 @@ If you want to execute processing just before executing an instruction of specif }); ``` -- `addBreakPoint` can set multiple breakpoints. +- `addBreakPoint` can set multiple breakpoints for the same address. - call `removeBreakPoint` or `removeAllBreakPoints` if you want to remove the break point(s). +- call `addBreakPointFP` if you want to use the function pointer. ### Use break operand @@ -224,8 +302,9 @@ If you want to execute processing just before executing an instruction of specif ``` - the opcode and length at break are stored in `opcode` and `opcodeLength` when the callback is made. -- `addBreakOperand` can set multiple breakpoints. +- `addBreakOperand` can set multiple breakpoints for the same operand. - call `removeBreakOperand` or `removeAllBreakOperands` if you want to remove the break operand(s). +- call `addBreakOperandFP` if you want to use the function pointer. ### Detect clock consuming @@ -277,6 +356,7 @@ CallHandler will be called back immediately **after** a branch by a CALL instruc - `addCallHandler` can set multiple CallHandlers. - call `removeAllCallHandlers` if you want to remove the CallHandler(s). +- call `addCallHandlerFP` if you want to use the function pointer. - CallHandler also catches branches caused by interrupts. - In the case of a condition-specified branch instruction, only the case where the branch is executed is callbacked. @@ -301,6 +381,7 @@ ReturnHandler will be called back immediately **before** a branch by a RET instr - `addReturnHandler` can set multiple ReturnHandlers. - call `removeAllReturnHandlers` if you want to remove the ReturnHandler(s). +- call `addReturnHandlerFP` if you want to use the function pointer. - In the case of a condition-specified branch instruction, only the case where the branch is executed is callbacked. ## License diff --git a/test-ex/Makefile b/test-ex/Makefile index 0b7ce19c..3bd8385c 100644 --- a/test-ex/Makefile +++ b/test-ex/Makefile @@ -1,5 +1,4 @@ -CFLAGS=-I../ \ - -std=c++11 \ +COMMON_FLAGS=-I../ \ -O2 \ -Wall \ -Wfloat-equal \ @@ -15,7 +14,7 @@ clean: -rm cpm cpm: cpm.cpp ../z80.hpp - clang $(CFLAGS) cpm.cpp -lstdc++ -o cpm + clang -std=c++17 $(COMMON_FLAGS) cpm.cpp -lstdc++ -o cpm zexdoc: cpm ./cpm -e zexdoc.cim @@ -24,8 +23,12 @@ zexall: cpm ./cpm -e zexall.cim ci: - g++-10 $(CFLAGS) -Wclass-memaccess cpm.cpp -lstdc++ -o cpm + @echo Test zexall with gcc + g++-10 -std=c++2a $(COMMON_FLAGS) -Wclass-memaccess cpm.cpp -lstdc++ -o cpm ./cpm -e -n zexall.cim + @echo Test zexdoc with clang + clang -std=c++17 $(COMMON_FLAGS) cpm.cpp -lstdc++ -o cpm + ./cpm -e -n zexdoc.cim full: cpm ./cpm zexall.cim diff --git a/test-ex/cpm.cpp b/test-ex/cpm.cpp index 05e45d58..84d4fec7 100644 --- a/test-ex/cpm.cpp +++ b/test-ex/cpm.cpp @@ -1,4 +1,5 @@ #include "../z80.hpp" +#include // CP/M Emulator (minimum implementation) class CPM { @@ -7,7 +8,6 @@ class CPM { unsigned char linePointer = 0; unsigned char memory[0x10000]; bool halted; - bool error; bool checkError; void (*lineCallback)(CPM*, char*); @@ -35,7 +35,6 @@ class CPM { fclose(fp); initBios(); halted = false; - error = false; checkError = false; clearLineBuffer(); lineCallback = NULL; @@ -126,38 +125,42 @@ int main(int argc, char* argv[]) } cpm.checkError = checkError; z80.reg.PC = 0x0100; - z80.addBreakOperand(0x76, [](void* arg, unsigned char* opcode, int opcodeLength) { + z80.addBreakOperandFP(0x76, [](void* arg, unsigned char* opcode, int opcodeLength) { ((CPM*)arg)->halted = true; }); - z80.addBreakPoint(0xFF04, [](void* arg) { + z80.addBreakPointFP(0xFF04, [](void* arg) { ((CPM*)arg)->halted = true; }); if (verboseMode) { - z80.setDebugMessage([](void* arg, const char* msg) { + z80.setDebugMessageFP([](void* arg, const char* msg) { puts(msg); }); } cpm.lineCallback = [](CPM* cpmPtr, char* line) { if (cpmPtr->checkError && strstr(line, "ERROR")) { cpmPtr->halted = true; - cpmPtr->error = true; } }; char animePattern[] = { '/', '-', '\\', '|' }; int anime = 0; - unsigned long totalClocks = 0; + long totalClocks = 0; + auto start = std::chrono::steady_clock::now(); + bool error = true; do { - totalClocks += (unsigned long)z80.execute(35795450); // 10sec in Z80A - if (cpm.error) { - printf("\rCPM detected an error at $%04X\n", z80.reg.PC); - } else if (cpm.halted) { - printf("CPM halted at $%04X (total: %luHz ... about %lu seconds in Z80A)\n", z80.reg.PC, totalClocks, totalClocks / 3579545); + totalClocks += (long)z80.execute(35795450); // 10sec in Z80A + if (cpm.halted) { + auto end = std::chrono::steady_clock::now(); + error = z80.reg.PC != 0xFF04; + printf("CPM halted at $%04X (total: %ldHz ... about %ld seconds in Z80A)\n", z80.reg.PC, totalClocks, totalClocks / 3579545); + long us = (long)std::chrono::duration_cast(end - start).count(); + long pw = totalClocks * 100000000 / 3579545 / us; + printf("Actual execution time: %ld.%ld seconds (x%ld.%ld times higher performance than Z80A)\n", us / 1000000, us % 1000000, pw / 100, pw % 100); } else if (!noAnimation) { putc(animePattern[anime++], stdout); anime &= 3; fflush(stdout); putc(0x08, stdout); } - } while (!cpm.halted && !cpm.error); - return cpm.error ? -1 : 0; + } while (!cpm.halted); + return error ? -1 : 0; } \ No newline at end of file diff --git a/test/Makefile b/test/Makefile index 705293e4..3cb8bbbe 100644 --- a/test/Makefile +++ b/test/Makefile @@ -7,15 +7,30 @@ CFLAGS=-I../ \ -Wsign-conversion \ -Wclass-varargs \ -Wtype-limits \ + -Wsequence-point \ + -Wunsequenced \ -Werror all: + make test-checkreg-on-callback + make test-execute make test-clock make test-status make test-im2 make test-branch make test-out make test-remove-break + make test-unknown + +test-execute: + clang $(CFLAGS) test-execute.cpp -lstdc++ + ./a.out > test-execute.txt + cat test-execute.txt + +test-unknown: + clang $(CFLAGS) test-unknown.cpp -lstdc++ + ./a.out > test-unknown.txt + cat test-unknown.txt test-clock: clang $(CFLAGS) test-clock.cpp -lstdc++ @@ -44,3 +59,8 @@ test-remove-break: clang $(CFLAGS) test-remove-break.cpp -lstdc++ ./a.out > test-remove-break.txt cat test-remove-break.txt + +test-checkreg-on-callback: + clang $(CFLAGS) test-checkreg-on-callback.cpp -lstdc++ + ./a.out > test-checkreg-on-callback.txt + cat test-checkreg-on-callback.txt diff --git a/test/test-branch.txt b/test/test-branch.txt index e6e4b401..de76f3a3 100644 --- a/test/test-branch.txt +++ b/test/test-branch.txt @@ -8,7 +8,7 @@ Executed a CALL instruction: - Return to: $0007 2 ** [0011] LD A<$FF>, $01 Detected a RET instruction: -- Branch from: $0013 +- Branch from: $0014 - Return to: $0007 1 * [0013] RET to $0007 (SP<$FFFB>) 1 * [0007] CP A<$01>, $FF @@ -18,12 +18,12 @@ Executed a CALL instruction: - Return to: $000C 2 ** [0014] LD A<$01>, $02 Detected a RET instruction: -- Branch from: $0016 +- Branch from: $0017 - Return to: $000C 1 * [0016] RET to $000C (SP<$FFFB>) 1 * [000C] CALL NC, $0017 (SP<$FFFD>) 1 * [000F] RET Z Detected a RET instruction: -- Branch from: $0010 +- Branch from: $0011 - Return to: $0003 0 [0010] RET NZ to $0003 (SP<$FFFD>) diff --git a/test/test-checkreg-on-callback.cpp b/test/test-checkreg-on-callback.cpp new file mode 100644 index 00000000..84a6c3e3 --- /dev/null +++ b/test/test-checkreg-on-callback.cpp @@ -0,0 +1,132 @@ +#include "z80.hpp" + +int main() +{ + unsigned short expectIndex = 0; + int expectAF[] = { + 0xFFFF, 0xFFFF, 0xFFFF, + 0x00FF, 0x00FF, 0x00FF, + 0x00FF, 0x00FF, 0x00FF, + 0x00FF, 0x00FF, 0x00FF, + 0x00FF, 0x00FF, 0x00FF, + 0x00FF, 0x00FF, 0x00FF, + 0x00FF, 0x00FF, 0x00FF, 0x00FF, + -1}; + int expectBC[] = { + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, + 0x8003, 0x8003, 0x8003, + 0x8003, 0x8003, 0x8003, + 0x8003, 0x8003, 0x8003, + 0x8003, 0x8003, 0x8003, 0x8003, + -1}; + int expectDE[] = { + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0004, + 0x8004, 0x8004, 0x8004, + 0x8004, 0x8004, 0x8004, + 0x8004, 0x8004, 0x8004, 0x8004, + -1}; + int expectHL[] = { + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0005, + 0x8005, 0x8005, 0x8005, + 0x8005, 0x8005, 0x8005, 0x8005, + -1}; + int expectPC[] = { + 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, + 0x0009, 0x000A, 0x000B, + 0x000C, 0x000D, 0x000E, + 0x000F, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0x0015, + -1}; + int expectSP[] = { + 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFF06, + 0x8006, 0x8006, 0x8006, 0x8006, + -1}; + int expectIX[] = { + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + -1}; + int expectIY[] = { + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + -1}; + unsigned char rom[256] = { + 0x3A, 0x01, 0x80, // LD A, (NN) + 0x32, 0x02, 0x80, // LD (NN), A + 0x01, 0x03, 0x80, // LD BC, NN + 0x11, 0x04, 0x80, // LD DE, NN + 0x21, 0x05, 0x80, // LD HL, NN + 0x31, 0x06, 0x80, // LD SP, NN + 0xDD, 0x36, 0x7F, 0xBB, // LD (IX+d), N + 0x00, // NOP (end test) + }; + Z80 z80([=, &expectIndex](void* arg, unsigned short addr) { + if (addr < 0x100 && -1 != expectAF[expectIndex]) { + unsigned short sp = ((Z80*)arg)->reg.SP; + unsigned short pc = ((Z80*)arg)->reg.PC; + unsigned short af = (unsigned short)(((Z80*)arg)->reg.pair.A * 256 + ((Z80*)arg)->reg.pair.F); + unsigned short bc = (unsigned short)(((Z80*)arg)->reg.pair.B * 256 + ((Z80*)arg)->reg.pair.C); + unsigned short de = (unsigned short)(((Z80*)arg)->reg.pair.D * 256 + ((Z80*)arg)->reg.pair.E); + unsigned short hl = (unsigned short)(((Z80*)arg)->reg.pair.H * 256 + ((Z80*)arg)->reg.pair.L); + unsigned short ix = ((Z80*)arg)->reg.IX; + unsigned short iy = ((Z80*)arg)->reg.IY; + printf("Read memory ... $%04X AF=%04X, BC=%04X, DE=%04X, HL=%04X, IX=%04X, IY=%04X, SP=%04X, PC=%04X\n", addr, af, bc, de, hl, ix, iy, sp, pc); + if (af != expectAF[expectIndex] || + bc != expectBC[expectIndex] || + de != expectDE[expectIndex] || + hl != expectHL[expectIndex] || + ix != expectIX[expectIndex] || + iy != expectIY[expectIndex] || + sp != expectSP[expectIndex] || + pc != expectPC[expectIndex]) { + puts("unexpected!"); + printf("expected: AF=%04X, BC=%04X, DE=%04X, HL=%04X, IX=%04X, IY=%04X, SP=%04X, PC=%04X\n", + expectAF[expectIndex], + expectBC[expectIndex], + expectDE[expectIndex], + expectHL[expectIndex], + expectIX[expectIndex], + expectIY[expectIndex], + expectSP[expectIndex], + expectPC[expectIndex]); + exit(-1); + } + expectIndex++; + return rom[addr]; + } + return (unsigned char)0x00; + }, [](void* arg, unsigned char addr, unsigned char value) { + }, [](void* arg, unsigned short port) { + return 0x00; + }, [](void* arg, unsigned short port, unsigned char value) { + }, &z80); + z80.setDebugMessage([](void* arg, const char* msg) { puts(msg); }); + z80.addBreakOperand(0x00, [](void* arg, unsigned char* op, int len) { exit(0); }); + z80.execute(INT_MAX); + return 0; +} diff --git a/test/test-checkreg-on-callback.txt b/test/test-checkreg-on-callback.txt new file mode 100644 index 00000000..5df2170f --- /dev/null +++ b/test/test-checkreg-on-callback.txt @@ -0,0 +1,29 @@ +Read memory ... $0000 AF=FFFF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0000 +Read memory ... $0001 AF=FFFF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0001 +Read memory ... $0002 AF=FFFF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0002 +[0000] LD A, ($8001) = $00 +Read memory ... $0003 AF=00FF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0003 +Read memory ... $0004 AF=00FF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0004 +Read memory ... $0005 AF=00FF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0005 +[0003] LD ($8002), A<$00> +Read memory ... $0006 AF=00FF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0006 +Read memory ... $0007 AF=00FF, BC=0000, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0007 +Read memory ... $0008 AF=00FF, BC=0003, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0008 +[0006] LD BC<$0000>, $8003 +Read memory ... $0009 AF=00FF, BC=8003, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=0009 +Read memory ... $000A AF=00FF, BC=8003, DE=0000, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=000A +Read memory ... $000B AF=00FF, BC=8003, DE=0004, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=000B +[0009] LD DE<$0000>, $8004 +Read memory ... $000C AF=00FF, BC=8003, DE=8004, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=000C +Read memory ... $000D AF=00FF, BC=8003, DE=8004, HL=0000, IX=0000, IY=0000, SP=FFFF, PC=000D +Read memory ... $000E AF=00FF, BC=8003, DE=8004, HL=0005, IX=0000, IY=0000, SP=FFFF, PC=000E +[000C] LD HL<$0000>, $8005 +Read memory ... $000F AF=00FF, BC=8003, DE=8004, HL=8005, IX=0000, IY=0000, SP=FFFF, PC=000F +Read memory ... $0010 AF=00FF, BC=8003, DE=8004, HL=8005, IX=0000, IY=0000, SP=FFFF, PC=0010 +Read memory ... $0011 AF=00FF, BC=8003, DE=8004, HL=8005, IX=0000, IY=0000, SP=FF06, PC=0011 +[000F] LD SP<$FFFF>, $8006 +Read memory ... $0012 AF=00FF, BC=8003, DE=8004, HL=8005, IX=0000, IY=0000, SP=8006, PC=0012 +Read memory ... $0013 AF=00FF, BC=8003, DE=8004, HL=8005, IX=0000, IY=0000, SP=8006, PC=0013 +Read memory ... $0014 AF=00FF, BC=8003, DE=8004, HL=8005, IX=0000, IY=0000, SP=8006, PC=0014 +Read memory ... $0015 AF=00FF, BC=8003, DE=8004, HL=8005, IX=0000, IY=0000, SP=8006, PC=0015 +[0012] LD (IX<$0000>+$7F), $BB diff --git a/test/test-execute.cpp b/test/test-execute.cpp new file mode 100644 index 00000000..dd318e8a --- /dev/null +++ b/test/test-execute.cpp @@ -0,0 +1,28 @@ +#include "z80.hpp" + +int main() +{ + unsigned char rom[256] = { + 0x01, 0x34, 0x12, // LD BC, $1234 + 0x3E, 0x01, // LD A, $01 + 0xED, 0x79, // OUT (C), A + 0xED, 0x78, // IN A, (C) + 0xc3, 0x09, 0x00, // JMP $0009 + }; + Z80 z80([=](void* arg, unsigned short addr) { return rom[addr & 0xFF]; }, + [](void* arg, unsigned short addr, unsigned char value) {}, + [](void* arg, unsigned short port) { return 0x00; }, + [](void* arg, unsigned short port, unsigned char value) { + // request break the execute function after output port operand has executed. + ((Z80*)arg)->requestBreak(); + }, &z80); + z80.setDebugMessage([](void* arg, const char* msg) { puts(msg); }); + z80.setConsumeClockCallback([](void* arg, int clocks) { printf("consume %dHz\n", clocks); }); + puts("===== execute(0) ====="); + printf("actualExecuteClocks = %dHz\n", z80.execute(0)); + puts("===== execute(1) ====="); + printf("actualExecuteClocks = %dHz\n", z80.execute(1)); + puts("===== execute(0x7FFFFFFF) ====="); + printf("actualExecuteClocks = %dHz\n", z80.execute(0x7FFFFFFF)); + return 0; +} diff --git a/test/test-execute.txt b/test/test-execute.txt new file mode 100644 index 00000000..57c2e7b5 --- /dev/null +++ b/test/test-execute.txt @@ -0,0 +1,20 @@ +===== execute(0) ===== +actualExecuteClocks = 0Hz +===== execute(1) ===== +consume 2Hz +consume 2Hz +consume 3Hz +consume 3Hz +[0000] LD BC<$0000>, $1234 +actualExecuteClocks = 10Hz +===== execute(0x7FFFFFFF) ===== +consume 2Hz +consume 2Hz +consume 3Hz +[0003] LD A<$FF>, $01 +consume 2Hz +consume 2Hz +consume 4Hz +[0005] OUT (C<$34>), A<$01> +consume 4Hz +actualExecuteClocks = 19Hz diff --git a/test/test-im2.txt b/test/test-im2.txt index 6ca55efd..073872fd 100644 --- a/test/test-im2.txt +++ b/test/test-im2.txt @@ -19,7 +19,7 @@ Executed a CALL instruction: - Branched to: $8002 - Return to: $0007 Detected a RET instruction: -- Branch from: $8002 +- Branch from: $8004 - Return to: $0007 [8002] RETI to $0007 (SP<$FFFD>) [0007] NOP diff --git a/test/test-unknown.cpp b/test/test-unknown.cpp new file mode 100644 index 00000000..a4d3dcb1 --- /dev/null +++ b/test/test-unknown.cpp @@ -0,0 +1,40 @@ +#include "z80.hpp" + +int main() +{ + unsigned char rom[] = { + 0xED, 0x30, // unknown ED + 0xDD, 0x1F, // unknown DD + 0xFD, 0x3F, // unknown FD + }; + Z80 z80([rom](void* arg, unsigned short addr) { + return rom[addr]; + }, [](void* arg, unsigned char addr, unsigned char value) { + }, [](void* arg, unsigned short port) { + return 0x00; + }, [](void* arg, unsigned short port, unsigned char value) { + }, &z80); + z80.setDebugMessage([](void* arg, const char* msg) { puts(msg); }); + + try { + z80.execute(1); + } catch(std::runtime_error& error) { + puts(error.what()); + if (strcmp(error.what(), "detect an unknown operand (ED,30)")) exit(-1); + } + + try { + z80.execute(1); + } catch(std::runtime_error& error) { + puts(error.what()); + if (strcmp(error.what(), "detect an unknown operand (DD,1F)")) exit(-1); + } + + try { + z80.execute(1); + } catch(std::runtime_error& error) { + puts(error.what()); + if (strcmp(error.what(), "detect an unknown operand (FD,3F)")) exit(-1); + } + return 0; +} diff --git a/test/test-unknown.txt b/test/test-unknown.txt new file mode 100644 index 00000000..9ea0d691 --- /dev/null +++ b/test/test-unknown.txt @@ -0,0 +1,3 @@ +detect an unknown operand (ED,30) +detect an unknown operand (DD,1F) +detect an unknown operand (FD,3F) diff --git a/z80.hpp b/z80.hpp index e5be3213..1aa8578b 100644 --- a/z80.hpp +++ b/z80.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -40,9 +41,9 @@ class Z80 { public: // Interface data types struct WaitClocks { - int fretch; // Wait T-cycle (Hz) before fetching instruction (default is 0 = no wait) - int read; // Wait T-cycle (Hz) before to read memory (default is 0 = no wait) - int write; // Wait T-cycle (Hz) before to write memory (default is 0 = no wait) + int fetch; // Wait T-cycle (Hz) before fetching instruction (default is 0 = no wait) + int read; // Wait T-cycle (Hz) before to read memory (default is 0 = no wait) + int write; // Wait T-cycle (Hz) before to write memory (default is 0 = no wait) } wtc; struct RegisterPair { @@ -125,21 +126,67 @@ class Z80 inline bool isFlagN() { return reg.pair.F & flagN(); } inline bool isFlagC() { return reg.pair.F & flagC(); } + inline bool checkConditionFlag(unsigned char c) + { + switch (c) { + case 0: return !isFlagZ(); + case 1: return isFlagZ(); + case 2: return !isFlagC(); + case 3: return isFlagC(); + case 4: return !isFlagPV(); + case 5: return isFlagPV(); + case 6: return !isFlagS(); + case 7: return isFlagS(); + default: return false; + } + } + inline unsigned char IFF1() { return 0b00000001; } inline unsigned char IFF2() { return 0b00000100; } inline unsigned char IFF_IRQ() { return 0b00100000; } inline unsigned char IFF_NMI() { return 0b01000000; } inline unsigned char IFF_HALT() { return 0b10000000; } + template + class CoExistenceCallback; + template + class CoExistenceCallback + { + private: + ReturnType (*fp)(ArgumentTypes...); + std::function fc; + + public: + CoExistenceCallback() { fp = nullptr; } + void setupAsFunctionObject(const std::function& fc_) { fc = fc_; } + void setupAsFunctionPointer(ReturnType (*fp_)(ArgumentTypes...)) { fp = fp_; } + inline ReturnType operator()(ArgumentTypes... args) { return fp ? fp(args...) : fc(args...); } + }; + class BreakPoint { public: unsigned short addr; - std::function callback; - BreakPoint(unsigned short addr_, const std::function& callback_) + CoExistenceCallback callback; + }; + + class BreakPointFC : public BreakPoint + { + public: + BreakPointFC(unsigned short addr_, const std::function& callback_) + { + this->addr = addr_; + this->callback.setupAsFunctionObject(callback_); + } + }; + + class BreakPointFP : public BreakPoint + { + public: + BreakPointFP(unsigned short addr_, void (*callback_)(void*)) { this->addr = addr_; - this->callback = std::bind(callback_, std::placeholders::_1); + this->callback.setupAsFunctionPointer(callback_); } }; @@ -148,64 +195,68 @@ class Z80 public: int prefixNumber; unsigned char operandNumber; - std::function callback; - BreakOperand(int prefixNumber_, unsigned char operandNumber_, const std::function& callback_) + CoExistenceCallback callback; + }; + + class BreakOperandFC : public BreakOperand + { + public: + BreakOperandFC(int prefixNumber_, unsigned char operandNumber_, const std::function& callback_) { this->prefixNumber = prefixNumber_; this->operandNumber = operandNumber_; - this->callback = std::bind(callback_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + this->callback.setupAsFunctionObject(callback_); } }; - class ReturnHandler + class BreakOperandFP : public BreakOperand { public: - std::function callback; - ReturnHandler(const std::function& callback_) + BreakOperandFP(int prefixNumber_, unsigned char operandNumber_, void (*callback_)(void*, unsigned char*, int)) { - this->callback = std::bind(callback_, std::placeholders::_1); + this->prefixNumber = prefixNumber_; + this->operandNumber = operandNumber_; + this->callback.setupAsFunctionPointer(callback_); } }; - inline void invokeReturnHandlers() + class SimpleHandler { - for (auto handler : this->CB.returnHandlers) { - handler->callback(this->CB.arg); + public: + CoExistenceCallback callback; + }; + + class SimpleHandlerFC : public SimpleHandler + { + public: + SimpleHandlerFC(const std::function& callback_) + { + this->callback.setupAsFunctionObject(callback_); } - } + }; - class CallHandler + class SimpleHandlerFP : public SimpleHandler { public: - std::function callback; - CallHandler(const std::function& callback_) + SimpleHandlerFP(void (*callback_)(void*)) { - this->callback = std::bind(callback_, std::placeholders::_1); + this->callback.setupAsFunctionPointer(callback_); } }; - inline void invokeCallHandlers() + inline void invokeReturnHandlers() { - for (auto handler : this->CB.callHandlers) { + for (auto handler : this->CB.returnHandlers) { handler->callback(this->CB.arg); } } - template - class CoExistenceCallback; - template - class CoExistenceCallback + inline void invokeCallHandlers() { - private: - ReturnType (*fp)(ArgumentTypes...); - std::function fc; - - public: - CoExistenceCallback() { fp = nullptr; } - void setupAsFunctionObject(const std::function& fc_) { fc = fc_; } - void setupAsFunctionPointer(ReturnType (*fp_)(ArgumentTypes...)) { fp = fp_; } - inline ReturnType operator()(ArgumentTypes... args) { return fp ? fp(args...) : fc(args...); } - }; + for (auto handler : this->CB.callHandlers) { + handler->callback(this->CB.arg); + } + } struct Callback { CoExistenceCallback read; @@ -219,8 +270,8 @@ class Z80 bool consumeClockEnabled; std::map*> breakPoints; std::map*> breakOperands; - std::vector returnHandlers; - std::vector callHandlers; + std::vector returnHandlers; + std::vector callHandlers; void* arg; } CB; @@ -243,7 +294,7 @@ class Z80 opcode[0] = operand->operandNumber; *opcodeLength = opLength1[opcode[0]]; for (int i = 1; i < *opcodeLength; i++) { - opcode[i] = readByte(reg.PC + i, 0); // read without consume clocks + opcode[i] = readByte(reg.PC + i - 1, 0); // read without consume clocks } break; case 0xCB: @@ -256,7 +307,7 @@ class Z80 opcode[1] = operand->operandNumber; *opcodeLength = opLengthED[opcode[1]]; for (int i = 2; i < *opcodeLength; i++) { - opcode[i] = readByte(reg.PC + i, 0); // read without consume clocks + opcode[i] = readByte(reg.PC + i - 2, 0); // read without consume clocks } break; case 0xDD: @@ -264,7 +315,7 @@ class Z80 opcode[1] = operand->operandNumber; *opcodeLength = opLengthIXY[opcode[1]]; for (int i = 2; i < *opcodeLength; i++) { - opcode[i] = readByte(reg.PC + i, 0); // read without consume clocks + opcode[i] = readByte(reg.PC + i - 2, 0); // read without consume clocks } break; case 0xFD: @@ -272,21 +323,21 @@ class Z80 opcode[1] = operand->operandNumber; *opcodeLength = opLengthIXY[opcode[1]]; for (int i = 2; i < *opcodeLength; i++) { - opcode[i] = readByte(reg.PC + i, 0); // read without consume clocks + opcode[i] = readByte(reg.PC + i - 2, 0); // read without consume clocks } break; case 0xDDCB: opcode[0] = 0xDD; opcode[1] = 0xCB; opcode[2] = operand->operandNumber; - opcode[3] = readByte(reg.PC + 3, 0); + opcode[3] = readByte(reg.PC, 0); *opcodeLength = 4; break; case 0xFDCB: opcode[0] = 0xFD; opcode[1] = 0xCB; opcode[2] = operand->operandNumber; - opcode[3] = readByte(reg.PC + 3, 0); + opcode[3] = readByte(reg.PC, 0); *opcodeLength = 4; break; } @@ -326,117 +377,23 @@ class Z80 CB.debugMessage(CB.arg, buf); } - inline unsigned short getAF() - { - unsigned short result = reg.pair.A; - result <<= 8; - result |= reg.pair.F; - return result; - } - - inline void setAF(unsigned short value) - { - reg.pair.A = (value & 0xFF00) >> 8; - reg.pair.F = (value & 0x00FF); - } - - inline unsigned short getAF2() - { - unsigned short result = reg.back.A; - result <<= 8; - result |= reg.back.F; - return result; - } - - inline void setAF2(unsigned short value) - { - reg.back.A = (value & 0xFF00) >> 8; - reg.back.F = (value & 0x00FF); - } - - inline unsigned short getBC() - { - unsigned short result = reg.pair.B; - result <<= 8; - result |= reg.pair.C; - return result; - } - - inline void setBC(unsigned short value) - { - reg.pair.B = (value & 0xFF00) >> 8; - reg.pair.C = (value & 0x00FF); - } - - inline unsigned short getBC2() - { - unsigned short result = reg.back.B; - result <<= 8; - result |= reg.back.C; - return result; - } - - inline void setBC2(unsigned short value) - { - reg.back.B = (value & 0xFF00) >> 8; - reg.back.C = (value & 0x00FF); - } - - inline unsigned short getDE() - { - unsigned short result = reg.pair.D; - result <<= 8; - result |= reg.pair.E; - return result; - } - - inline void setDE(unsigned short value) - { - reg.pair.D = (value & 0xFF00) >> 8; - reg.pair.E = (value & 0x00FF); - } - - inline unsigned short getDE2() - { - unsigned short result = reg.back.D; - result <<= 8; - result |= reg.back.E; - return result; - } - - inline void setDE2(unsigned short value) - { - reg.back.D = (value & 0xFF00) >> 8; - reg.back.E = (value & 0x00FF); - } - - inline unsigned short getHL() - { - unsigned short result = reg.pair.H; - result <<= 8; - result |= reg.pair.L; - return result; - } - - inline void setHL(unsigned short value) - { - reg.pair.H = (value & 0xFF00) >> 8; - reg.pair.L = (value & 0x00FF); - } - - inline unsigned short getHL2() - { - unsigned short result = reg.back.H; - result <<= 8; - result |= reg.back.L; - return result; - } - - inline void setHL2(unsigned short value) - { - reg.back.H = (value & 0xFF00) >> 8; - reg.back.L = (value & 0x00FF); - } + inline unsigned short getAF() { return make16BitsFromLE(reg.pair.F, reg.pair.A); } + inline unsigned short getAF2() { return make16BitsFromLE(reg.back.F, reg.back.A); } + inline unsigned short getBC() { return make16BitsFromLE(reg.pair.C, reg.pair.B); } + inline unsigned short getBC2() { return make16BitsFromLE(reg.back.C, reg.back.B); } + inline unsigned short getDE() { return make16BitsFromLE(reg.pair.E, reg.pair.D); } + inline unsigned short getDE2() { return make16BitsFromLE(reg.back.E, reg.back.D); } + inline unsigned short getHL() { return make16BitsFromLE(reg.pair.L, reg.pair.H); } + inline unsigned short getHL2() { return make16BitsFromLE(reg.back.L, reg.back.H); } + + inline void setAF(unsigned short value) { splitTo8BitsPair(value, ®.pair.A, ®.pair.F); } + inline void setAF2(unsigned short value) { splitTo8BitsPair(value, ®.back.A, ®.back.F); } + inline void setBC(unsigned short value) { splitTo8BitsPair(value, ®.pair.B, ®.pair.C); } + inline void setBC2(unsigned short value) { splitTo8BitsPair(value, ®.back.B, ®.back.C); } + inline void setDE(unsigned short value) { splitTo8BitsPair(value, ®.pair.D, ®.pair.E); } + inline void setDE2(unsigned short value) { splitTo8BitsPair(value, ®.back.D, ®.back.E); } + inline void setHL(unsigned short value) { splitTo8BitsPair(value, ®.pair.H, ®.pair.L); } + inline void setHL2(unsigned short value) { splitTo8BitsPair(value, ®.back.H, ®.back.L); } inline unsigned short getRP(unsigned char rp) { @@ -470,32 +427,24 @@ class Z80 inline void setRP(unsigned char rp, unsigned short value) { - unsigned char h = (value & 0xFF00) >> 8; - unsigned char l = value & 0x00FF; switch (rp & 0b11) { - case 0b00: { - reg.pair.B = h; - reg.pair.C = l; - break; - } - case 0b01: { - reg.pair.D = h; - reg.pair.E = l; - break; - } - case 0b10: { - reg.pair.H = h; - reg.pair.L = l; - break; - } + case 0b00: setBC(value); break; + case 0b01: setDE(value); break; + case 0b10: setHL(value); break; default: reg.SP = value; } } inline unsigned char getIXH() { return (reg.IX & 0xFF00) >> 8; } - inline unsigned char getIXL() { return reg.IX & 0x00Ff; } + inline unsigned char getIXL() { return reg.IX & 0x00FF; } inline unsigned char getIYH() { return (reg.IY & 0xFF00) >> 8; } - inline unsigned char getIYL() { return reg.IY & 0x00Ff; } + inline unsigned char getIYL() { return reg.IY & 0x00FF; } + inline unsigned char getPCH() { return (reg.PC & 0xFF00) >> 8; } + inline unsigned char getPCL() { return reg.PC & 0x00FF; } + inline void setPCH(unsigned char v) { reg.PC = (reg.PC & 0x00FF) + v * 256; } + inline void setPCL(unsigned char v) { reg.PC = (reg.PC & 0xFF00) + v; } + inline void setSPH(unsigned char v) { reg.SP = (reg.SP & 0x00FF) + v * 256; } + inline void setSPL(unsigned char v) { reg.SP = (reg.SP & 0xFF00) + v; } inline void setIXH(unsigned char v) { reg.IX = (reg.IX & 0x00FF) + v * 256; } inline void setIXL(unsigned char v) { reg.IX = (reg.IX & 0xFF00) + v; } inline void setIYH(unsigned char v) { reg.IY = (reg.IY & 0x00FF) + v * 256; } @@ -523,13 +472,7 @@ class Z80 return hz; } - inline unsigned short getPort16(unsigned char c) - { - unsigned short result = (unsigned short)reg.pair.B; - result <<= 8; - result |= c; - return result; - } + inline unsigned short getPort16(unsigned char c) { return make16BitsFromLE(c, reg.pair.B); } inline unsigned char inPort(unsigned char port, int clock = 4) { @@ -544,290 +487,267 @@ class Z80 consumeClock(clock); } - static inline int NOP(Z80* ctx) + static inline void NOP(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] NOP", ctx->reg.PC); - ctx->reg.PC++; - return 0; + if (ctx->isDebug()) ctx->log("[%04X] NOP", ctx->reg.PC - 1); } - static inline int HALT(Z80* ctx) + static inline void HALT(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] HALT", ctx->reg.PC); + if (ctx->isDebug()) ctx->log("[%04X] HALT", ctx->reg.PC - 1); ctx->reg.IFF |= ctx->IFF_HALT(); - ctx->reg.PC++; - return 0; } - static inline int DI(Z80* ctx) + static inline void DI(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] DI", ctx->reg.PC); + if (ctx->isDebug()) ctx->log("[%04X] DI", ctx->reg.PC - 1); ctx->reg.IFF &= ~(ctx->IFF1() | ctx->IFF2()); - ctx->reg.PC++; - return 0; } - static inline int EI(Z80* ctx) + static inline void EI(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] EI", ctx->reg.PC); + if (ctx->isDebug()) ctx->log("[%04X] EI", ctx->reg.PC - 1); ctx->reg.IFF |= ctx->IFF1() | ctx->IFF2(); - ctx->reg.PC++; ctx->reg.execEI = 1; - return 0; } - static inline int IM0(Z80* ctx) { return ctx->IM(0); } - static inline int IM1(Z80* ctx) { return ctx->IM(1); } - static inline int IM2(Z80* ctx) { return ctx->IM(2); } - inline int IM(unsigned char interrptMode) + static inline void IM0(Z80* ctx) { ctx->IM(0); } + static inline void IM1(Z80* ctx) { ctx->IM(1); } + static inline void IM2(Z80* ctx) { ctx->IM(2); } + inline void IM(unsigned char interrptMode) { - if (isDebug()) log("[%04X] IM %d", reg.PC, interrptMode); + if (isDebug()) log("[%04X] IM %d", reg.PC - 2, interrptMode); reg.interrupt &= 0b11111100; reg.interrupt |= interrptMode & 0b11; - reg.PC += 2; - return 0; } - static inline int LD_A_I_(Z80* ctx) { return ctx->LD_A_I(); } - inline int LD_A_I() + static inline void LD_A_I_(Z80* ctx) { ctx->LD_A_I(); } + inline void LD_A_I() { - if (isDebug()) log("[%04X] LD A<$%02X>, I<$%02X>", reg.PC, reg.pair.A, reg.I); + if (isDebug()) log("[%04X] LD A<$%02X>, I<$%02X>", reg.PC - 2, reg.pair.A, reg.I); reg.pair.A = reg.I; setFlagPV(reg.IFF & IFF2()); - reg.PC += 2; - return consumeClock(1); + consumeClock(1); } - static inline int LD_I_A_(Z80* ctx) { return ctx->LD_I_A(); } - inline int LD_I_A() + static inline void LD_I_A_(Z80* ctx) { ctx->LD_I_A(); } + inline void LD_I_A() { - if (isDebug()) log("[%04X] LD I<$%02X>, A<$%02X>", reg.PC, reg.I, reg.pair.A); + if (isDebug()) log("[%04X] LD I<$%02X>, A<$%02X>", reg.PC - 2, reg.I, reg.pair.A); reg.I = reg.pair.A; - reg.PC += 2; - return consumeClock(1); + consumeClock(1); } - static inline int LD_A_R_(Z80* ctx) { return ctx->LD_A_R(); } - inline int LD_A_R() + static inline void LD_A_R_(Z80* ctx) { ctx->LD_A_R(); } + inline void LD_A_R() { - if (isDebug()) log("[%04X] LD A<$%02X>, R<$%02X>", reg.PC, reg.pair.A, reg.R); + if (isDebug()) log("[%04X] LD A<$%02X>, R<$%02X>", reg.PC - 2, reg.pair.A, reg.R); reg.pair.A = reg.R; setFlagPV(reg.IFF & IFF1()); - reg.PC += 2; - return consumeClock(1); + consumeClock(1); } - static inline int LD_R_A_(Z80* ctx) { return ctx->LD_R_A(); } - inline int LD_R_A() + static inline void LD_R_A_(Z80* ctx) { ctx->LD_R_A(); } + inline void LD_R_A() { - if (isDebug()) log("[%04X] LD R<$%02X>, A<$%02X>", reg.PC, reg.R, reg.pair.A); + if (isDebug()) log("[%04X] LD R<$%02X>, A<$%02X>", reg.PC - 2, reg.R, reg.pair.A); reg.R = reg.pair.A; - reg.PC += 2; - return consumeClock(1); + consumeClock(1); } - static inline int OP_CB(Z80* ctx) + static inline void OP_CB(Z80* ctx) { - unsigned char operandNumber = ctx->readByte(ctx->reg.PC + 1); + unsigned char operandNumber = ctx->fetch(4); ctx->checkBreakOperandCB(operandNumber); - return ctx->opSetCB[operandNumber](ctx); + ctx->opSetCB[operandNumber](ctx); } - static inline int OP_ED(Z80* ctx) + static inline void OP_ED(Z80* ctx) { - unsigned char operandNumber = ctx->readByte(ctx->reg.PC + 1); + unsigned char operandNumber = ctx->fetch(4); + if (!ctx->opSetED[operandNumber]) { + char buf[80]; + snprintf(buf, sizeof(buf), "detect an unknown operand (ED,%02X)", operandNumber); + throw std::runtime_error(buf); + } ctx->checkBreakOperandED(operandNumber); - return ctx->opSetED[operandNumber](ctx); + ctx->opSetED[operandNumber](ctx); } - static inline int OP_IX(Z80* ctx) + static inline void OP_IX(Z80* ctx) { - unsigned char operandNumber = ctx->readByte(ctx->reg.PC + 1); + unsigned char operandNumber = ctx->fetch(4); + if (!ctx->opSetIX[operandNumber]) { + char buf[80]; + snprintf(buf, sizeof(buf), "detect an unknown operand (DD,%02X)", operandNumber); + throw std::runtime_error(buf); + } ctx->checkBreakOperandIX(operandNumber); - return ctx->opSetIX[operandNumber](ctx); + ctx->opSetIX[operandNumber](ctx); } - static inline int OP_IY(Z80* ctx) + static inline void OP_IY(Z80* ctx) { - unsigned char operandNumber = ctx->readByte(ctx->reg.PC + 1); + unsigned char operandNumber = ctx->fetch(4); + if (!ctx->opSetIY[operandNumber]) { + char buf[80]; + snprintf(buf, sizeof(buf), "detect an unknown operand (FD,%02X)", operandNumber); + throw std::runtime_error(buf); + } ctx->checkBreakOperandIY(operandNumber); - return ctx->opSetIY[operandNumber](ctx); + ctx->opSetIY[operandNumber](ctx); } - static inline int OP_IX4(Z80* ctx) + static inline void OP_IX4(Z80* ctx) { - signed char op3 = (signed char)ctx->readByte(ctx->reg.PC + 2); - unsigned char op4 = ctx->readByte(ctx->reg.PC + 3); + signed char op3 = (signed char)ctx->fetch(4); + unsigned char op4 = ctx->fetch(4); ctx->checkBreakOperandIX4(op4); - return ctx->opSetIX4[op4](ctx, op3); + ctx->opSetIX4[op4](ctx, op3); } - static inline int OP_IY4(Z80* ctx) + static inline void OP_IY4(Z80* ctx) { - signed char op3 = (signed char)ctx->readByte(ctx->reg.PC + 2); - unsigned char op4 = ctx->readByte(ctx->reg.PC + 3); + signed char op3 = (signed char)ctx->fetch(4); + unsigned char op4 = ctx->fetch(4); ctx->checkBreakOperandIY4(op4); - return ctx->opSetIY4[op4](ctx, op3); + ctx->opSetIY4[op4](ctx, op3); } // Load location (HL) with value n - static inline int LD_HL_N(Z80* ctx) + static inline void LD_HL_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); + unsigned char n = ctx->fetch(3); unsigned short hl = ctx->getHL(); - if (ctx->isDebug()) ctx->log("[%04X] LD (HL<$%04X>), $%02X", ctx->reg.PC, hl, n); + if (ctx->isDebug()) ctx->log("[%04X] LD (HL<$%04X>), $%02X", ctx->reg.PC - 2, hl, n); ctx->writeByte(hl, n, 3); - ctx->reg.PC += 2; - return 0; } // Load Acc. wth location (BC) - static inline int LD_A_BC(Z80* ctx) + static inline void LD_A_BC(Z80* ctx) { unsigned short addr = ctx->getBC(); unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] LD A, (BC<$%02X%02X>) = $%02X", ctx->reg.PC, ctx->reg.pair.B, ctx->reg.pair.C, n); + if (ctx->isDebug()) ctx->log("[%04X] LD A, (BC<$%02X%02X>) = $%02X", ctx->reg.PC - 1, ctx->reg.pair.B, ctx->reg.pair.C, n); ctx->reg.pair.A = n; - ctx->reg.PC++; - return 0; } // Load Acc. wth location (DE) - static inline int LD_A_DE(Z80* ctx) + static inline void LD_A_DE(Z80* ctx) { unsigned short addr = ctx->getDE(); unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] LD A, (DE<$%02X%02X>) = $%02X", ctx->reg.PC, ctx->reg.pair.D, ctx->reg.pair.E, n); + if (ctx->isDebug()) ctx->log("[%04X] LD A, (DE<$%02X%02X>) = $%02X", ctx->reg.PC - 1, ctx->reg.pair.D, ctx->reg.pair.E, n); ctx->reg.pair.A = n; - ctx->reg.PC++; - return 0; } // Load Acc. wth location (nn) - static inline int LD_A_NN(Z80* ctx) + static inline void LD_A_NN(Z80* ctx) { - unsigned short addr = ctx->readByte(ctx->reg.PC + 1, 3); - addr += ctx->readByte(ctx->reg.PC + 2, 3) << 8; + unsigned char l = ctx->fetch(3); + unsigned char h = ctx->fetch(3); + unsigned short addr = ctx->make16BitsFromLE(l, h); unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] LD A, ($%04X) = $%02X", ctx->reg.PC, addr, n); + if (ctx->isDebug()) ctx->log("[%04X] LD A, ($%04X) = $%02X", ctx->reg.PC - 3, addr, n); ctx->reg.pair.A = n; - ctx->reg.PC += 3; - return 0; } // Load location (BC) wtih Acc. - static inline int LD_BC_A(Z80* ctx) + static inline void LD_BC_A(Z80* ctx) { unsigned short addr = ctx->getBC(); unsigned char n = ctx->reg.pair.A; - if (ctx->isDebug()) ctx->log("[%04X] LD (BC<$%02X%02X>), A<$%02X>", ctx->reg.PC, ctx->reg.pair.B, ctx->reg.pair.C, n); + if (ctx->isDebug()) ctx->log("[%04X] LD (BC<$%02X%02X>), A<$%02X>", ctx->reg.PC - 1, ctx->reg.pair.B, ctx->reg.pair.C, n); ctx->writeByte(addr, n, 3); - ctx->reg.PC++; - return 0; } // Load location (DE) wtih Acc. - static inline int LD_DE_A(Z80* ctx) + static inline void LD_DE_A(Z80* ctx) { unsigned short addr = ctx->getDE(); unsigned char n = ctx->reg.pair.A; - if (ctx->isDebug()) ctx->log("[%04X] LD (DE<$%02X%02X>), A<$%02X>", ctx->reg.PC, ctx->reg.pair.D, ctx->reg.pair.E, n); + if (ctx->isDebug()) ctx->log("[%04X] LD (DE<$%02X%02X>), A<$%02X>", ctx->reg.PC - 1, ctx->reg.pair.D, ctx->reg.pair.E, n); ctx->writeByte(addr, n, 3); - ctx->reg.PC++; - return 0; } // Load location (nn) with Acc. - static inline int LD_NN_A(Z80* ctx) + static inline void LD_NN_A(Z80* ctx) { - unsigned short addr = ctx->readByte(ctx->reg.PC + 1, 3); - addr += ctx->readByte(ctx->reg.PC + 2, 3) << 8; + unsigned char l = ctx->fetch(3); + unsigned char h = ctx->fetch(3); + unsigned short addr = ctx->make16BitsFromLE(l, h); unsigned char n = ctx->reg.pair.A; - if (ctx->isDebug()) ctx->log("[%04X] LD ($%04X), A<$%02X>", ctx->reg.PC, addr, n); + if (ctx->isDebug()) ctx->log("[%04X] LD ($%04X), A<$%02X>", ctx->reg.PC - 3, addr, n); ctx->writeByte(addr, n, 3); - ctx->reg.PC += 3; - return 0; } // Load HL with location (nn). - static inline int LD_HL_ADDR(Z80* ctx) - { - unsigned char nL = ctx->readByte(ctx->reg.PC + 1, 3); - unsigned char nH = ctx->readByte(ctx->reg.PC + 2, 3); - unsigned short addr = (nH << 8) + nL; - unsigned char l = ctx->readByte(addr, 3); - unsigned char h = ctx->readByte(addr + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] LD HL<$%04X>, ($%04X) = $%02X%02X", ctx->reg.PC, ctx->getHL(), addr, h, l); - ctx->reg.pair.L = l; - ctx->reg.pair.H = h; - ctx->reg.PC += 3; - return 0; + static inline void LD_HL_ADDR(Z80* ctx) + { + unsigned char l = ctx->fetch(3); + unsigned char h = ctx->fetch(3); + unsigned short addr = ctx->make16BitsFromLE(l, h); + unsigned short hl = ctx->getHL(); + ctx->reg.pair.L = ctx->readByte(addr, 3); + ctx->reg.pair.H = ctx->readByte(addr + 1, 3); + if (ctx->isDebug()) ctx->log("[%04X] LD HL<$%04X>, ($%04X) = $%04X", ctx->reg.PC - 3, hl, addr, ctx->getHL()); } // Load location (nn) with HL. - static inline int LD_ADDR_HL(Z80* ctx) + static inline void LD_ADDR_HL(Z80* ctx) { - unsigned char nL = ctx->readByte(ctx->reg.PC + 1, 3); - unsigned char nH = ctx->readByte(ctx->reg.PC + 2, 3); - unsigned short addr = (nH << 8) + nL; - if (ctx->isDebug()) ctx->log("[%04X] LD ($%04X), %s", ctx->reg.PC, addr, ctx->registerPairDump(0b10)); + unsigned char l = ctx->fetch(3); + unsigned char h = ctx->fetch(3); + unsigned short addr = ctx->make16BitsFromLE(l, h); + if (ctx->isDebug()) ctx->log("[%04X] LD ($%04X), %s", ctx->reg.PC - 3, addr, ctx->registerPairDump(0b10)); ctx->writeByte(addr, ctx->reg.pair.L, 3); ctx->writeByte(addr + 1, ctx->reg.pair.H, 3); - ctx->reg.PC += 3; - return 0; } // Load SP with HL. - static inline int LD_SP_HL(Z80* ctx) + static inline void LD_SP_HL(Z80* ctx) { - unsigned short value = ctx->getHL(); - if (ctx->isDebug()) ctx->log("[%04X] LD %s, HL<$%04X>", ctx->reg.PC, ctx->registerPairDump(0b11), value); - ctx->reg.SP = value; - ctx->reg.PC++; - return ctx->consumeClock(2); + if (ctx->isDebug()) ctx->log("[%04X] LD %s, HL<$%04X>", ctx->reg.PC - 1, ctx->registerPairDump(0b11), ctx->getHL()); + ctx->reg.SP = ctx->getHL(); + ctx->consumeClock(2); } // Exchange H and L with D and E - static inline int EX_DE_HL(Z80* ctx) + static inline void EX_DE_HL(Z80* ctx) { unsigned short de = ctx->getDE(); unsigned short hl = ctx->getHL(); - if (ctx->isDebug()) ctx->log("[%04X] EX %s, %s", ctx->reg.PC, ctx->registerPairDump(0b01), ctx->registerPairDump(0b10)); + if (ctx->isDebug()) ctx->log("[%04X] EX %s, %s", ctx->reg.PC - 1, ctx->registerPairDump(0b01), ctx->registerPairDump(0b10)); ctx->setDE(hl); ctx->setHL(de); - ctx->reg.PC++; - return 0; } // Exchange A and F with A' and F' - static inline int EX_AF_AF2(Z80* ctx) + static inline void EX_AF_AF2(Z80* ctx) { unsigned short af = ctx->getAF(); unsigned short af2 = ctx->getAF2(); - if (ctx->isDebug()) ctx->log("[%04X] EX AF<$%02X%02X>, AF'<$%02X%02X>", ctx->reg.PC, ctx->reg.pair.A, ctx->reg.pair.F, ctx->reg.back.A, ctx->reg.back.F); + if (ctx->isDebug()) ctx->log("[%04X] EX AF<$%02X%02X>, AF'<$%02X%02X>", ctx->reg.PC - 1, ctx->reg.pair.A, ctx->reg.pair.F, ctx->reg.back.A, ctx->reg.back.F); ctx->setAF(af2); ctx->setAF2(af); - ctx->reg.PC++; - return 0; } - static inline int EX_SP_HL(Z80* ctx) + static inline void EX_SP_HL(Z80* ctx) { - unsigned char l = ctx->readByte(ctx->reg.SP); - unsigned char h = ctx->readByte(ctx->reg.SP + 1); + unsigned short sp = ctx->reg.SP; + unsigned char l = ctx->pop(4); + unsigned char h = ctx->pop(4); unsigned short hl = ctx->getHL(); - if (ctx->isDebug()) ctx->log("[%04X] EX (SP<$%04X>) = $%02X%02X, HL<$%04X>", ctx->reg.PC, ctx->reg.SP, h, l, hl); - ctx->writeByte(ctx->reg.SP, ctx->reg.pair.L); - ctx->writeByte(ctx->reg.SP + 1, ctx->reg.pair.H, 3); - ctx->reg.pair.L = l; + if (ctx->isDebug()) ctx->log("[%04X] EX (SP<$%04X>) = $%02X%02X, HL<$%04X>", ctx->reg.PC - 1, sp, h, l, hl); + ctx->push(ctx->reg.pair.H, 4); ctx->reg.pair.H = h; - ctx->reg.PC++; - return 0; + ctx->push(ctx->reg.pair.L, 3); + ctx->reg.pair.L = l; } - static inline int EXX(Z80* ctx) + static inline void EXX(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] EXX", ctx->reg.PC); + if (ctx->isDebug()) ctx->log("[%04X] EXX", ctx->reg.PC - 1); unsigned short bc = ctx->getBC(); unsigned short bc2 = ctx->getBC2(); unsigned short de = ctx->getDE(); @@ -840,29 +760,33 @@ class Z80 ctx->setDE2(de); ctx->setHL(hl2); ctx->setHL2(hl); - ctx->reg.PC++; - return 0; } - static inline int PUSH_AF(Z80* ctx) + inline void push(unsigned char value, int clocks) { - if (ctx->isDebug()) ctx->log("[%04X] PUSH AF<$%02X%02X> ", ctx->reg.PC, ctx->reg.pair.A, ctx->reg.pair.F, ctx->reg.SP); - ctx->writeByte(--ctx->reg.SP, ctx->reg.pair.A); - ctx->writeByte(--ctx->reg.SP, ctx->reg.pair.F, 3); - ctx->reg.PC++; - return 0; + reg.SP--; + writeByte(reg.SP, value, clocks); } - static inline int POP_AF(Z80* ctx) + inline unsigned char pop(int clocks) { - unsigned short sp = ctx->reg.SP; - unsigned char l = ctx->readByte(ctx->reg.SP++, 3); - unsigned char h = ctx->readByte(ctx->reg.SP++, 3); - if (ctx->isDebug()) ctx->log("[%04X] POP AF = $%02X%02X", ctx->reg.PC, sp, h, l); - ctx->reg.pair.F = l; - ctx->reg.pair.A = h; - ctx->reg.PC++; - return 0; + unsigned char value = readByte(reg.SP, clocks); + reg.SP++; + return value; + } + + static inline void PUSH_AF(Z80* ctx) + { + if (ctx->isDebug()) ctx->log("[%04X] PUSH AF<$%02X%02X> ", ctx->reg.PC - 1, ctx->reg.pair.A, ctx->reg.pair.F, ctx->reg.SP); + ctx->push(ctx->reg.pair.A, 4); + ctx->push(ctx->reg.pair.F, 3); + } + + static inline void POP_AF(Z80* ctx) + { + ctx->reg.pair.F = ctx->pop(3); + ctx->reg.pair.A = ctx->pop(3); + if (ctx->isDebug()) ctx->log("[%04X] POP AF = $%04X", ctx->reg.PC - 1, ctx->reg.SP - 2, ctx->getAF()); } inline unsigned char* getRegisterPointer(unsigned char r) @@ -881,6 +805,22 @@ class Z80 return nullptr; } + inline unsigned char getRegister(unsigned char r) + { + switch (r) { + case 0b111: return reg.pair.A; + case 0b000: return reg.pair.B; + case 0b001: return reg.pair.C; + case 0b010: return reg.pair.D; + case 0b011: return reg.pair.E; + case 0b100: return reg.pair.H; + case 0b101: return reg.pair.L; + case 0b110: return reg.pair.F; + } + if (isDebug()) log("detected an unknown register number: $%02X", r); + return 0xFF; + } + inline char* registerDump(unsigned char r) { static char A[16]; @@ -924,15 +864,15 @@ class Z80 return CN; } - inline char* relativeDump(signed char e) + inline char* relativeDump(unsigned short pc, signed char e) { static char buf[80]; if (e < 0) { int ee = -e; ee -= 2; - snprintf(buf, sizeof(buf), "$%04X - %d = $%04X", reg.PC, ee, reg.PC + e + 2); + snprintf(buf, sizeof(buf), "$%04X - %d = $%04X", pc, ee, pc + e + 2); } else { - snprintf(buf, sizeof(buf), "$%04X + %d = $%04X", reg.PC, e + 2, reg.PC + e + 2); + snprintf(buf, sizeof(buf), "$%04X + %d = $%04X", pc, e + 2, pc + e + 2); } return buf; } @@ -1008,508 +948,444 @@ class Z80 } // Load Reg. r1 with Reg. r2 - static inline int LD_B_B(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b000); } - static inline int LD_B_C(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b001); } - static inline int LD_B_D(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b010); } - static inline int LD_B_E(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b011); } - static inline int LD_B_B_2(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b000, 2); } - static inline int LD_B_C_2(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b001, 2); } - static inline int LD_B_D_2(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b010, 2); } - static inline int LD_B_E_2(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b011, 2); } - static inline int LD_B_H(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b100); } - static inline int LD_B_L(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b101); } - static inline int LD_B_A(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b111); } - static inline int LD_C_B(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b000); } - static inline int LD_C_C(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b001); } - static inline int LD_C_D(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b010); } - static inline int LD_C_E(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b011); } - static inline int LD_B_A_2(Z80* ctx) { return ctx->LD_R1_R2(0b000, 0b111, 2); } - static inline int LD_C_B_2(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b000, 2); } - static inline int LD_C_C_2(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b001, 2); } - static inline int LD_C_D_2(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b010, 2); } - static inline int LD_C_E_2(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b011, 2); } - static inline int LD_C_H(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b100); } - static inline int LD_C_L(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b101); } - static inline int LD_C_A(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b111); } - static inline int LD_D_B(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b000); } - static inline int LD_D_C(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b001); } - static inline int LD_D_D(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b010); } - static inline int LD_D_E(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b011); } - static inline int LD_C_A_2(Z80* ctx) { return ctx->LD_R1_R2(0b001, 0b111, 2); } - static inline int LD_D_B_2(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b000, 2); } - static inline int LD_D_C_2(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b001, 2); } - static inline int LD_D_D_2(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b010, 2); } - static inline int LD_D_E_2(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b011, 2); } - static inline int LD_D_H(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b100); } - static inline int LD_D_L(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b101); } - static inline int LD_D_A(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b111); } - static inline int LD_E_B(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b000); } - static inline int LD_E_C(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b001); } - static inline int LD_E_D(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b010); } - static inline int LD_E_E(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b011); } - static inline int LD_D_A_2(Z80* ctx) { return ctx->LD_R1_R2(0b010, 0b111, 2); } - static inline int LD_E_B_2(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b000, 2); } - static inline int LD_E_C_2(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b001, 2); } - static inline int LD_E_D_2(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b010, 2); } - static inline int LD_E_E_2(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b011, 2); } - static inline int LD_E_H(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b100); } - static inline int LD_E_L(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b101); } - static inline int LD_E_A(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b111); } - static inline int LD_E_A_2(Z80* ctx) { return ctx->LD_R1_R2(0b011, 0b111, 2); } - static inline int LD_H_B(Z80* ctx) { return ctx->LD_R1_R2(0b100, 0b000); } - static inline int LD_H_C(Z80* ctx) { return ctx->LD_R1_R2(0b100, 0b001); } - static inline int LD_H_D(Z80* ctx) { return ctx->LD_R1_R2(0b100, 0b010); } - static inline int LD_H_E(Z80* ctx) { return ctx->LD_R1_R2(0b100, 0b011); } - static inline int LD_H_H(Z80* ctx) { return ctx->LD_R1_R2(0b100, 0b100); } - static inline int LD_H_L(Z80* ctx) { return ctx->LD_R1_R2(0b100, 0b101); } - static inline int LD_H_A(Z80* ctx) { return ctx->LD_R1_R2(0b100, 0b111); } - static inline int LD_L_B(Z80* ctx) { return ctx->LD_R1_R2(0b101, 0b000); } - static inline int LD_L_C(Z80* ctx) { return ctx->LD_R1_R2(0b101, 0b001); } - static inline int LD_L_D(Z80* ctx) { return ctx->LD_R1_R2(0b101, 0b010); } - static inline int LD_L_E(Z80* ctx) { return ctx->LD_R1_R2(0b101, 0b011); } - static inline int LD_L_H(Z80* ctx) { return ctx->LD_R1_R2(0b101, 0b100); } - static inline int LD_L_L(Z80* ctx) { return ctx->LD_R1_R2(0b101, 0b101); } - static inline int LD_L_A(Z80* ctx) { return ctx->LD_R1_R2(0b101, 0b111); } - static inline int LD_A_B(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b000); } - static inline int LD_A_C(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b001); } - static inline int LD_A_D(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b010); } - static inline int LD_A_E(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b011); } - static inline int LD_A_B_2(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b000, 2); } - static inline int LD_A_C_2(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b001, 2); } - static inline int LD_A_D_2(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b010, 2); } - static inline int LD_A_E_2(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b011, 2); } - static inline int LD_A_H(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b100); } - static inline int LD_A_L(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b101); } - static inline int LD_A_A(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b111); } - static inline int LD_A_A_2(Z80* ctx) { return ctx->LD_R1_R2(0b111, 0b111, 2); } - inline int LD_R1_R2(unsigned char r1, unsigned char r2, int counter = 1) + static inline void LD_B_B(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b000); } + static inline void LD_B_C(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b001); } + static inline void LD_B_D(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b010); } + static inline void LD_B_E(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b011); } + static inline void LD_B_B_2(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b000, 2); } + static inline void LD_B_C_2(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b001, 2); } + static inline void LD_B_D_2(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b010, 2); } + static inline void LD_B_E_2(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b011, 2); } + static inline void LD_B_H(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b100); } + static inline void LD_B_L(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b101); } + static inline void LD_B_A(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b111); } + static inline void LD_C_B(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b000); } + static inline void LD_C_C(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b001); } + static inline void LD_C_D(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b010); } + static inline void LD_C_E(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b011); } + static inline void LD_B_A_2(Z80* ctx) { ctx->LD_R1_R2(0b000, 0b111, 2); } + static inline void LD_C_B_2(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b000, 2); } + static inline void LD_C_C_2(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b001, 2); } + static inline void LD_C_D_2(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b010, 2); } + static inline void LD_C_E_2(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b011, 2); } + static inline void LD_C_H(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b100); } + static inline void LD_C_L(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b101); } + static inline void LD_C_A(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b111); } + static inline void LD_D_B(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b000); } + static inline void LD_D_C(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b001); } + static inline void LD_D_D(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b010); } + static inline void LD_D_E(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b011); } + static inline void LD_C_A_2(Z80* ctx) { ctx->LD_R1_R2(0b001, 0b111, 2); } + static inline void LD_D_B_2(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b000, 2); } + static inline void LD_D_C_2(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b001, 2); } + static inline void LD_D_D_2(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b010, 2); } + static inline void LD_D_E_2(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b011, 2); } + static inline void LD_D_H(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b100); } + static inline void LD_D_L(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b101); } + static inline void LD_D_A(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b111); } + static inline void LD_E_B(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b000); } + static inline void LD_E_C(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b001); } + static inline void LD_E_D(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b010); } + static inline void LD_E_E(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b011); } + static inline void LD_D_A_2(Z80* ctx) { ctx->LD_R1_R2(0b010, 0b111, 2); } + static inline void LD_E_B_2(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b000, 2); } + static inline void LD_E_C_2(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b001, 2); } + static inline void LD_E_D_2(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b010, 2); } + static inline void LD_E_E_2(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b011, 2); } + static inline void LD_E_H(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b100); } + static inline void LD_E_L(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b101); } + static inline void LD_E_A(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b111); } + static inline void LD_E_A_2(Z80* ctx) { ctx->LD_R1_R2(0b011, 0b111, 2); } + static inline void LD_H_B(Z80* ctx) { ctx->LD_R1_R2(0b100, 0b000); } + static inline void LD_H_C(Z80* ctx) { ctx->LD_R1_R2(0b100, 0b001); } + static inline void LD_H_D(Z80* ctx) { ctx->LD_R1_R2(0b100, 0b010); } + static inline void LD_H_E(Z80* ctx) { ctx->LD_R1_R2(0b100, 0b011); } + static inline void LD_H_H(Z80* ctx) { ctx->LD_R1_R2(0b100, 0b100); } + static inline void LD_H_L(Z80* ctx) { ctx->LD_R1_R2(0b100, 0b101); } + static inline void LD_H_A(Z80* ctx) { ctx->LD_R1_R2(0b100, 0b111); } + static inline void LD_L_B(Z80* ctx) { ctx->LD_R1_R2(0b101, 0b000); } + static inline void LD_L_C(Z80* ctx) { ctx->LD_R1_R2(0b101, 0b001); } + static inline void LD_L_D(Z80* ctx) { ctx->LD_R1_R2(0b101, 0b010); } + static inline void LD_L_E(Z80* ctx) { ctx->LD_R1_R2(0b101, 0b011); } + static inline void LD_L_H(Z80* ctx) { ctx->LD_R1_R2(0b101, 0b100); } + static inline void LD_L_L(Z80* ctx) { ctx->LD_R1_R2(0b101, 0b101); } + static inline void LD_L_A(Z80* ctx) { ctx->LD_R1_R2(0b101, 0b111); } + static inline void LD_A_B(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b000); } + static inline void LD_A_C(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b001); } + static inline void LD_A_D(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b010); } + static inline void LD_A_E(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b011); } + static inline void LD_A_B_2(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b000, 2); } + static inline void LD_A_C_2(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b001, 2); } + static inline void LD_A_D_2(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b010, 2); } + static inline void LD_A_E_2(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b011, 2); } + static inline void LD_A_H(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b100); } + static inline void LD_A_L(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b101); } + static inline void LD_A_A(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b111); } + static inline void LD_A_A_2(Z80* ctx) { ctx->LD_R1_R2(0b111, 0b111, 2); } + inline void LD_R1_R2(unsigned char r1, unsigned char r2, int counter = 1) { unsigned char* r1p = getRegisterPointer(r1); unsigned char* r2p = getRegisterPointer(r2); - if (isDebug()) log("[%04X] LD %s, %s", reg.PC, registerDump(r1), registerDump(r2)); + if (isDebug()) log("[%04X] LD %s, %s", reg.PC - counter, registerDump(r1), registerDump(r2)); if (r1p && r2p) *r1p = *r2p; - reg.PC += counter; - return 0; } // Load Reg. r with value n - static inline int LD_A_N(Z80* ctx) { return ctx->LD_R_N(0b111); } - static inline int LD_B_N(Z80* ctx) { return ctx->LD_R_N(0b000); } - static inline int LD_C_N(Z80* ctx) { return ctx->LD_R_N(0b001); } - static inline int LD_D_N(Z80* ctx) { return ctx->LD_R_N(0b010); } - static inline int LD_E_N(Z80* ctx) { return ctx->LD_R_N(0b011); } - static inline int LD_H_N(Z80* ctx) { return ctx->LD_R_N(0b100); } - static inline int LD_L_N(Z80* ctx) { return ctx->LD_R_N(0b101); } - static inline int LD_A_N_3(Z80* ctx) { return ctx->LD_R_N(0b111, 3); } - static inline int LD_B_N_3(Z80* ctx) { return ctx->LD_R_N(0b000, 3); } - static inline int LD_C_N_3(Z80* ctx) { return ctx->LD_R_N(0b001, 3); } - static inline int LD_D_N_3(Z80* ctx) { return ctx->LD_R_N(0b010, 3); } - static inline int LD_E_N_3(Z80* ctx) { return ctx->LD_R_N(0b011, 3); } - static inline int LD_H_N_3(Z80* ctx) { return ctx->LD_R_N(0b100, 3); } - static inline int LD_L_N_3(Z80* ctx) { return ctx->LD_R_N(0b101, 3); } - inline int LD_R_N(unsigned char r, int pc = 2) + static inline void LD_A_N(Z80* ctx) { ctx->LD_R_N(0b111); } + static inline void LD_B_N(Z80* ctx) { ctx->LD_R_N(0b000); } + static inline void LD_C_N(Z80* ctx) { ctx->LD_R_N(0b001); } + static inline void LD_D_N(Z80* ctx) { ctx->LD_R_N(0b010); } + static inline void LD_E_N(Z80* ctx) { ctx->LD_R_N(0b011); } + static inline void LD_H_N(Z80* ctx) { ctx->LD_R_N(0b100); } + static inline void LD_L_N(Z80* ctx) { ctx->LD_R_N(0b101); } + static inline void LD_A_N_3(Z80* ctx) { ctx->LD_R_N(0b111, 3); } + static inline void LD_B_N_3(Z80* ctx) { ctx->LD_R_N(0b000, 3); } + static inline void LD_C_N_3(Z80* ctx) { ctx->LD_R_N(0b001, 3); } + static inline void LD_D_N_3(Z80* ctx) { ctx->LD_R_N(0b010, 3); } + static inline void LD_E_N_3(Z80* ctx) { ctx->LD_R_N(0b011, 3); } + inline void LD_R_N(unsigned char r, int pc = 2) { unsigned char* rp = getRegisterPointer(r); - unsigned char n = readByte(reg.PC + 1, 3); - if (isDebug()) log("[%04X] LD %s, $%02X", reg.PC, registerDump(r), n); + unsigned char n = fetch(3); + if (isDebug()) log("[%04X] LD %s, $%02X", reg.PC - pc, registerDump(r), n); if (rp) *rp = n; - reg.PC += pc; - return 0; } // Load Reg. IX(high) with value n - static inline int LD_IXH_N_(Z80* ctx) { return ctx->LD_IXH_N(); } - inline int LD_IXH_N() + static inline void LD_IXH_N_(Z80* ctx) { ctx->LD_IXH_N(); } + inline void LD_IXH_N() { - unsigned char n = readByte(reg.PC + 2, 3); - if (isDebug()) log("[%04X] LD IXH, $%02X", reg.PC, n); + unsigned char n = fetch(3); + if (isDebug()) log("[%04X] LD IXH, $%02X", reg.PC - 3, n); setIXH(n); - reg.PC += 3; - return 0; } // Load Reg. IX(high) with value Reg. - static inline int LD_IXH_A(Z80* ctx) { return ctx->LD_IXH_R(0b111); } - static inline int LD_IXH_B(Z80* ctx) { return ctx->LD_IXH_R(0b000); } - static inline int LD_IXH_C(Z80* ctx) { return ctx->LD_IXH_R(0b001); } - static inline int LD_IXH_D(Z80* ctx) { return ctx->LD_IXH_R(0b010); } - static inline int LD_IXH_E(Z80* ctx) { return ctx->LD_IXH_R(0b011); } - inline int LD_IXH_R(unsigned char r) + static inline void LD_IXH_A(Z80* ctx) { ctx->LD_IXH_R(0b111); } + static inline void LD_IXH_B(Z80* ctx) { ctx->LD_IXH_R(0b000); } + static inline void LD_IXH_C(Z80* ctx) { ctx->LD_IXH_R(0b001); } + static inline void LD_IXH_D(Z80* ctx) { ctx->LD_IXH_R(0b010); } + static inline void LD_IXH_E(Z80* ctx) { ctx->LD_IXH_R(0b011); } + inline void LD_IXH_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD IXH, %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] LD IXH, %s", reg.PC - 2, registerDump(r)); setIXH(*rp); - reg.PC += 2; - return 0; } // Load Reg. IX(high) with value IX(high) - static inline int LD_IXH_IXH_(Z80* ctx) { return ctx->LD_IXH_IXH(); } - inline int LD_IXH_IXH() + static inline void LD_IXH_IXH_(Z80* ctx) { ctx->LD_IXH_IXH(); } + inline void LD_IXH_IXH() { - if (isDebug()) log("[%04X] LD IXH, IXH<$%02X>", reg.PC, getIXH()); - // nothing to do - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] LD IXH, IXH<$%02X>", reg.PC - 2, getIXH()); } // Load Reg. IX(high) with value IX(low) - static inline int LD_IXH_IXL_(Z80* ctx) { return ctx->LD_IXH_IXL(); } - inline int LD_IXH_IXL() + static inline void LD_IXH_IXL_(Z80* ctx) { ctx->LD_IXH_IXL(); } + inline void LD_IXH_IXL() { - if (isDebug()) log("[%04X] LD IXH, IXL<$%02X>", reg.PC, getIXL()); + if (isDebug()) log("[%04X] LD IXH, IXL<$%02X>", reg.PC - 2, getIXL()); setIXH(getIXL()); - reg.PC += 2; - return 0; } // Load Reg. IX(low) with value n - static inline int LD_IXL_N_(Z80* ctx) { return ctx->LD_IXL_N(); } - inline int LD_IXL_N() + static inline void LD_IXL_N_(Z80* ctx) { ctx->LD_IXL_N(); } + inline void LD_IXL_N() { - unsigned char n = readByte(reg.PC + 2, 3); - if (isDebug()) log("[%04X] LD IXL, $%02X", reg.PC, n); + unsigned char n = fetch(3); + if (isDebug()) log("[%04X] LD IXL, $%02X", reg.PC - 3, n); setIXL(n); - reg.PC += 3; - return 0; } // Load Reg. IX(low) with value Reg. - static inline int LD_IXL_A(Z80* ctx) { return ctx->LD_IXL_R(0b111); } - static inline int LD_IXL_B(Z80* ctx) { return ctx->LD_IXL_R(0b000); } - static inline int LD_IXL_C(Z80* ctx) { return ctx->LD_IXL_R(0b001); } - static inline int LD_IXL_D(Z80* ctx) { return ctx->LD_IXL_R(0b010); } - static inline int LD_IXL_E(Z80* ctx) { return ctx->LD_IXL_R(0b011); } - inline int LD_IXL_R(unsigned char r) + static inline void LD_IXL_A(Z80* ctx) { ctx->LD_IXL_R(0b111); } + static inline void LD_IXL_B(Z80* ctx) { ctx->LD_IXL_R(0b000); } + static inline void LD_IXL_C(Z80* ctx) { ctx->LD_IXL_R(0b001); } + static inline void LD_IXL_D(Z80* ctx) { ctx->LD_IXL_R(0b010); } + static inline void LD_IXL_E(Z80* ctx) { ctx->LD_IXL_R(0b011); } + inline void LD_IXL_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD IXL, %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] LD IXL, %s", reg.PC - 2, registerDump(r)); setIXL(*rp); - reg.PC += 2; - return 0; } // Load Reg. IX(low) with value IX(high) - static inline int LD_IXL_IXH_(Z80* ctx) { return ctx->LD_IXL_IXH(); } - inline int LD_IXL_IXH() + static inline void LD_IXL_IXH_(Z80* ctx) { ctx->LD_IXL_IXH(); } + inline void LD_IXL_IXH() { - if (isDebug()) log("[%04X] LD IXL, IXH<$%02X>", reg.PC, getIXH()); + if (isDebug()) log("[%04X] LD IXL, IXH<$%02X>", reg.PC - 2, getIXH()); setIXL(getIXH()); - reg.PC += 2; - return 0; } // Load Reg. IX(low) with value IX(low) - static inline int LD_IXL_IXL_(Z80* ctx) { return ctx->LD_IXL_IXL(); } - inline int LD_IXL_IXL() + static inline void LD_IXL_IXL_(Z80* ctx) { ctx->LD_IXL_IXL(); } + inline void LD_IXL_IXL() { - if (isDebug()) log("[%04X] LD IXL, IXL<$%02X>", reg.PC, getIXL()); - // nothing to do - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] LD IXL, IXL<$%02X>", reg.PC - 2, getIXL()); } // Load Reg. IY(high) with value n - static inline int LD_IYH_N_(Z80* ctx) { return ctx->LD_IYH_N(); } - inline int LD_IYH_N() + static inline void LD_IYH_N_(Z80* ctx) { ctx->LD_IYH_N(); } + inline void LD_IYH_N() { - unsigned char n = readByte(reg.PC + 2, 3); - if (isDebug()) log("[%04X] LD IYH, $%02X", reg.PC, n); + unsigned char n = fetch(3); + if (isDebug()) log("[%04X] LD IYH, $%02X", reg.PC - 3, n); setIYH(n); - reg.PC += 3; - return 0; } // Load Reg. IY(high) with value Reg. - static inline int LD_IYH_A(Z80* ctx) { return ctx->LD_IYH_R(0b111); } - static inline int LD_IYH_B(Z80* ctx) { return ctx->LD_IYH_R(0b000); } - static inline int LD_IYH_C(Z80* ctx) { return ctx->LD_IYH_R(0b001); } - static inline int LD_IYH_D(Z80* ctx) { return ctx->LD_IYH_R(0b010); } - static inline int LD_IYH_E(Z80* ctx) { return ctx->LD_IYH_R(0b011); } - inline int LD_IYH_R(unsigned char r) + static inline void LD_IYH_A(Z80* ctx) { ctx->LD_IYH_R(0b111); } + static inline void LD_IYH_B(Z80* ctx) { ctx->LD_IYH_R(0b000); } + static inline void LD_IYH_C(Z80* ctx) { ctx->LD_IYH_R(0b001); } + static inline void LD_IYH_D(Z80* ctx) { ctx->LD_IYH_R(0b010); } + static inline void LD_IYH_E(Z80* ctx) { ctx->LD_IYH_R(0b011); } + inline void LD_IYH_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD IYH, %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] LD IYH, %s", reg.PC - 2, registerDump(r)); setIYH(*rp); - reg.PC += 2; - return 0; } // Load Reg. IY(high) with value IY(high) - static inline int LD_IYH_IYH_(Z80* ctx) { return ctx->LD_IYH_IYH(); } - inline int LD_IYH_IYH() + static inline void LD_IYH_IYH_(Z80* ctx) { ctx->LD_IYH_IYH(); } + inline void LD_IYH_IYH() { - if (isDebug()) log("[%04X] LD IYH, IYH<$%02X>", reg.PC, getIYH()); - // nothing to do - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] LD IYH, IYH<$%02X>", reg.PC - 2, getIYH()); } // Load Reg. IY(high) with value IY(low) - static inline int LD_IYH_IYL_(Z80* ctx) { return ctx->LD_IYH_IYL(); } - inline int LD_IYH_IYL() + static inline void LD_IYH_IYL_(Z80* ctx) { ctx->LD_IYH_IYL(); } + inline void LD_IYH_IYL() { - if (isDebug()) log("[%04X] LD IYH, IYL<$%02X>", reg.PC, getIYL()); + if (isDebug()) log("[%04X] LD IYH, IYL<$%02X>", reg.PC - 2, getIYL()); setIYH(getIYL()); - reg.PC += 2; - return 0; } // Load Reg. IY(low) with value n - static inline int LD_IYL_N_(Z80* ctx) { return ctx->LD_IYL_N(); } - inline int LD_IYL_N() + static inline void LD_IYL_N_(Z80* ctx) { ctx->LD_IYL_N(); } + inline void LD_IYL_N() { - unsigned char n = readByte(reg.PC + 2, 3); - if (isDebug()) log("[%04X] LD IYL, $%02X", reg.PC, n); + unsigned char n = fetch(3); + if (isDebug()) log("[%04X] LD IYL, $%02X", reg.PC - 3, n); setIYL(n); - reg.PC += 3; - return 0; } // Load Reg. IY(low) with value Reg. - static inline int LD_IYL_A(Z80* ctx) { return ctx->LD_IYL_R(0b111); } - static inline int LD_IYL_B(Z80* ctx) { return ctx->LD_IYL_R(0b000); } - static inline int LD_IYL_C(Z80* ctx) { return ctx->LD_IYL_R(0b001); } - static inline int LD_IYL_D(Z80* ctx) { return ctx->LD_IYL_R(0b010); } - static inline int LD_IYL_E(Z80* ctx) { return ctx->LD_IYL_R(0b011); } - inline int LD_IYL_R(unsigned char r) + static inline void LD_IYL_A(Z80* ctx) { ctx->LD_IYL_R(0b111); } + static inline void LD_IYL_B(Z80* ctx) { ctx->LD_IYL_R(0b000); } + static inline void LD_IYL_C(Z80* ctx) { ctx->LD_IYL_R(0b001); } + static inline void LD_IYL_D(Z80* ctx) { ctx->LD_IYL_R(0b010); } + static inline void LD_IYL_E(Z80* ctx) { ctx->LD_IYL_R(0b011); } + inline void LD_IYL_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD IYL, %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] LD IYL, %s", reg.PC - 2, registerDump(r)); setIYL(*rp); - reg.PC += 2; - return 0; } // Load Reg. IY(low) with value IY(high) - static inline int LD_IYL_IYH_(Z80* ctx) { return ctx->LD_IYL_IYH(); } - inline int LD_IYL_IYH() + static inline void LD_IYL_IYH_(Z80* ctx) { ctx->LD_IYL_IYH(); } + inline void LD_IYL_IYH() { - if (isDebug()) log("[%04X] LD IYL, IYH<$%02X>", reg.PC, getIYH()); + if (isDebug()) log("[%04X] LD IYL, IYH<$%02X>", reg.PC - 2, getIYH()); setIYL(getIYH()); - reg.PC += 2; - return 0; } // Load Reg. IY(low) with value IY(low) - static inline int LD_IYL_IYL_(Z80* ctx) { return ctx->LD_IYL_IYL(); } - inline int LD_IYL_IYL() + static inline void LD_IYL_IYL_(Z80* ctx) { ctx->LD_IYL_IYL(); } + inline void LD_IYL_IYL() { - if (isDebug()) log("[%04X] LD IYL, IYL<$%02X>", reg.PC, getIYL()); - // nothing to do - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] LD IYL, IYL<$%02X>", reg.PC - 2, getIYL()); } // Load Reg. r with location (HL) - static inline int LD_B_HL(Z80* ctx) { return ctx->LD_R_HL(0b000); } - static inline int LD_C_HL(Z80* ctx) { return ctx->LD_R_HL(0b001); } - static inline int LD_D_HL(Z80* ctx) { return ctx->LD_R_HL(0b010); } - static inline int LD_E_HL(Z80* ctx) { return ctx->LD_R_HL(0b011); } - static inline int LD_H_HL(Z80* ctx) { return ctx->LD_R_HL(0b100); } - static inline int LD_L_HL(Z80* ctx) { return ctx->LD_R_HL(0b101); } - static inline int LD_A_HL(Z80* ctx) { return ctx->LD_R_HL(0b111); } - inline int LD_R_HL(unsigned char r) + static inline void LD_B_HL(Z80* ctx) { ctx->LD_R_HL(0b000); } + static inline void LD_C_HL(Z80* ctx) { ctx->LD_R_HL(0b001); } + static inline void LD_D_HL(Z80* ctx) { ctx->LD_R_HL(0b010); } + static inline void LD_E_HL(Z80* ctx) { ctx->LD_R_HL(0b011); } + static inline void LD_H_HL(Z80* ctx) { ctx->LD_R_HL(0b100); } + static inline void LD_L_HL(Z80* ctx) { ctx->LD_R_HL(0b101); } + static inline void LD_A_HL(Z80* ctx) { ctx->LD_R_HL(0b111); } + inline void LD_R_HL(unsigned char r) { unsigned char* rp = getRegisterPointer(r); unsigned char n = readByte(getHL(), 3); - if (isDebug()) log("[%04X] LD %s, (%s) = $%02X", reg.PC, registerDump(r), registerPairDump(0b10), n); + if (isDebug()) log("[%04X] LD %s, (%s) = $%02X", reg.PC - 1, registerDump(r), registerPairDump(0b10), n); if (rp) *rp = n; - reg.PC += 1; - return 0; } // Load Reg. r with location (IX+d) - static inline int LD_A_IX(Z80* ctx) { return ctx->LD_R_IX(0b111); } - static inline int LD_B_IX(Z80* ctx) { return ctx->LD_R_IX(0b000); } - static inline int LD_C_IX(Z80* ctx) { return ctx->LD_R_IX(0b001); } - static inline int LD_D_IX(Z80* ctx) { return ctx->LD_R_IX(0b010); } - static inline int LD_E_IX(Z80* ctx) { return ctx->LD_R_IX(0b011); } - static inline int LD_H_IX(Z80* ctx) { return ctx->LD_R_IX(0b100); } - static inline int LD_L_IX(Z80* ctx) { return ctx->LD_R_IX(0b101); } - inline int LD_R_IX(unsigned char r) + static inline void LD_A_IX(Z80* ctx) { ctx->LD_R_IX(0b111); } + static inline void LD_B_IX(Z80* ctx) { ctx->LD_R_IX(0b000); } + static inline void LD_C_IX(Z80* ctx) { ctx->LD_R_IX(0b001); } + static inline void LD_D_IX(Z80* ctx) { ctx->LD_R_IX(0b010); } + static inline void LD_E_IX(Z80* ctx) { ctx->LD_R_IX(0b011); } + static inline void LD_H_IX(Z80* ctx) { ctx->LD_R_IX(0b100); } + static inline void LD_L_IX(Z80* ctx) { ctx->LD_R_IX(0b101); } + inline void LD_R_IX(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned char n = readByte((reg.IX + d) & 0xFFFF); - if (isDebug()) log("[%04X] LD %s, (IX<$%04X>+$%02X) = $%02X", reg.PC, registerDump(r), reg.IX, d, n); + if (isDebug()) log("[%04X] LD %s, (IX<$%04X>+$%02X) = $%02X", reg.PC - 3, registerDump(r), reg.IX, d, n); if (rp) *rp = n; - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Load Reg. r with IXH - static inline int LD_A_IXH(Z80* ctx) { return ctx->LD_R_IXH(0b111); } - static inline int LD_B_IXH(Z80* ctx) { return ctx->LD_R_IXH(0b000); } - static inline int LD_C_IXH(Z80* ctx) { return ctx->LD_R_IXH(0b001); } - static inline int LD_D_IXH(Z80* ctx) { return ctx->LD_R_IXH(0b010); } - static inline int LD_E_IXH(Z80* ctx) { return ctx->LD_R_IXH(0b011); } - inline int LD_R_IXH(unsigned char r) + static inline void LD_A_IXH(Z80* ctx) { ctx->LD_R_IXH(0b111); } + static inline void LD_B_IXH(Z80* ctx) { ctx->LD_R_IXH(0b000); } + static inline void LD_C_IXH(Z80* ctx) { ctx->LD_R_IXH(0b001); } + static inline void LD_D_IXH(Z80* ctx) { ctx->LD_R_IXH(0b010); } + static inline void LD_E_IXH(Z80* ctx) { ctx->LD_R_IXH(0b011); } + inline void LD_R_IXH(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD %s, IXH<$%02X>", reg.PC, registerDump(r), getIXH()); + if (isDebug()) log("[%04X] LD %s, IXH<$%02X>", reg.PC - 2, registerDump(r), getIXH()); if (rp) *rp = getIXH(); - reg.PC += 2; - return 0; } // Load Reg. r with IXL - static inline int LD_A_IXL(Z80* ctx) { return ctx->LD_R_IXL(0b111); } - static inline int LD_B_IXL(Z80* ctx) { return ctx->LD_R_IXL(0b000); } - static inline int LD_C_IXL(Z80* ctx) { return ctx->LD_R_IXL(0b001); } - static inline int LD_D_IXL(Z80* ctx) { return ctx->LD_R_IXL(0b010); } - static inline int LD_E_IXL(Z80* ctx) { return ctx->LD_R_IXL(0b011); } - inline int LD_R_IXL(unsigned char r) + static inline void LD_A_IXL(Z80* ctx) { ctx->LD_R_IXL(0b111); } + static inline void LD_B_IXL(Z80* ctx) { ctx->LD_R_IXL(0b000); } + static inline void LD_C_IXL(Z80* ctx) { ctx->LD_R_IXL(0b001); } + static inline void LD_D_IXL(Z80* ctx) { ctx->LD_R_IXL(0b010); } + static inline void LD_E_IXL(Z80* ctx) { ctx->LD_R_IXL(0b011); } + inline void LD_R_IXL(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD %s, IXL<$%02X>", reg.PC, registerDump(r), getIXL()); + if (isDebug()) log("[%04X] LD %s, IXL<$%02X>", reg.PC - 2, registerDump(r), getIXL()); if (rp) *rp = getIXL(); - reg.PC += 2; - return 0; } // Load Reg. r with location (IY+d) - static inline int LD_A_IY(Z80* ctx) { return ctx->LD_R_IY(0b111); } - static inline int LD_B_IY(Z80* ctx) { return ctx->LD_R_IY(0b000); } - static inline int LD_C_IY(Z80* ctx) { return ctx->LD_R_IY(0b001); } - static inline int LD_D_IY(Z80* ctx) { return ctx->LD_R_IY(0b010); } - static inline int LD_E_IY(Z80* ctx) { return ctx->LD_R_IY(0b011); } - static inline int LD_H_IY(Z80* ctx) { return ctx->LD_R_IY(0b100); } - static inline int LD_L_IY(Z80* ctx) { return ctx->LD_R_IY(0b101); } - inline int LD_R_IY(unsigned char r) + static inline void LD_A_IY(Z80* ctx) { ctx->LD_R_IY(0b111); } + static inline void LD_B_IY(Z80* ctx) { ctx->LD_R_IY(0b000); } + static inline void LD_C_IY(Z80* ctx) { ctx->LD_R_IY(0b001); } + static inline void LD_D_IY(Z80* ctx) { ctx->LD_R_IY(0b010); } + static inline void LD_E_IY(Z80* ctx) { ctx->LD_R_IY(0b011); } + static inline void LD_H_IY(Z80* ctx) { ctx->LD_R_IY(0b100); } + static inline void LD_L_IY(Z80* ctx) { ctx->LD_R_IY(0b101); } + inline void LD_R_IY(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned char n = readByte((reg.IY + d) & 0xFFFF); - if (isDebug()) log("[%04X] LD %s, (IY<$%04X>+$%02X) = $%02X", reg.PC, registerDump(r), reg.IY, d, n); + if (isDebug()) log("[%04X] LD %s, (IY<$%04X>+$%02X) = $%02X", reg.PC - 3, registerDump(r), reg.IY, d, n); if (rp) *rp = n; - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Load Reg. r with IYH - static inline int LD_A_IYH(Z80* ctx) { return ctx->LD_R_IYH(0b111); } - static inline int LD_B_IYH(Z80* ctx) { return ctx->LD_R_IYH(0b000); } - static inline int LD_C_IYH(Z80* ctx) { return ctx->LD_R_IYH(0b001); } - static inline int LD_D_IYH(Z80* ctx) { return ctx->LD_R_IYH(0b010); } - static inline int LD_E_IYH(Z80* ctx) { return ctx->LD_R_IYH(0b011); } - inline int LD_R_IYH(unsigned char r) - { - unsigned char iyh = (reg.IY & 0xFF00) >> 8; + static inline void LD_A_IYH(Z80* ctx) { ctx->LD_R_IYH(0b111); } + static inline void LD_B_IYH(Z80* ctx) { ctx->LD_R_IYH(0b000); } + static inline void LD_C_IYH(Z80* ctx) { ctx->LD_R_IYH(0b001); } + static inline void LD_D_IYH(Z80* ctx) { ctx->LD_R_IYH(0b010); } + static inline void LD_E_IYH(Z80* ctx) { ctx->LD_R_IYH(0b011); } + inline void LD_R_IYH(unsigned char r) + { + unsigned char iyh = getIYH(); unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD %s, IYH<$%02X>", reg.PC, registerDump(r), iyh); + if (isDebug()) log("[%04X] LD %s, IYH<$%02X>", reg.PC - 2, registerDump(r), iyh); if (rp) *rp = iyh; - reg.PC += 2; - return 0; } // Load Reg. r with IYL - static inline int LD_A_IYL(Z80* ctx) { return ctx->LD_R_IYL(0b111); } - static inline int LD_B_IYL(Z80* ctx) { return ctx->LD_R_IYL(0b000); } - static inline int LD_C_IYL(Z80* ctx) { return ctx->LD_R_IYL(0b001); } - static inline int LD_D_IYL(Z80* ctx) { return ctx->LD_R_IYL(0b010); } - static inline int LD_E_IYL(Z80* ctx) { return ctx->LD_R_IYL(0b011); } - inline int LD_R_IYL(unsigned char r) - { - unsigned char iyl = reg.IY & 0x00FF; + static inline void LD_A_IYL(Z80* ctx) { ctx->LD_R_IYL(0b111); } + static inline void LD_B_IYL(Z80* ctx) { ctx->LD_R_IYL(0b000); } + static inline void LD_C_IYL(Z80* ctx) { ctx->LD_R_IYL(0b001); } + static inline void LD_D_IYL(Z80* ctx) { ctx->LD_R_IYL(0b010); } + static inline void LD_E_IYL(Z80* ctx) { ctx->LD_R_IYL(0b011); } + inline void LD_R_IYL(unsigned char r) + { + unsigned char iyl = getIYL(); unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] LD %s, IYL<$%02X>", reg.PC, registerDump(r), iyl); + if (isDebug()) log("[%04X] LD %s, IYL<$%02X>", reg.PC - 2, registerDump(r), iyl); if (rp) *rp = iyl; - reg.PC += 2; - return 0; } // Load location (HL) with Reg. r - static inline int LD_HL_B(Z80* ctx) { return ctx->LD_HL_R(0b000); } - static inline int LD_HL_C(Z80* ctx) { return ctx->LD_HL_R(0b001); } - static inline int LD_HL_D(Z80* ctx) { return ctx->LD_HL_R(0b010); } - static inline int LD_HL_E(Z80* ctx) { return ctx->LD_HL_R(0b011); } - static inline int LD_HL_H(Z80* ctx) { return ctx->LD_HL_R(0b100); } - static inline int LD_HL_L(Z80* ctx) { return ctx->LD_HL_R(0b101); } - static inline int LD_HL_A(Z80* ctx) { return ctx->LD_HL_R(0b111); } - inline int LD_HL_R(unsigned char r) + static inline void LD_HL_B(Z80* ctx) { ctx->LD_HL_R(0b000); } + static inline void LD_HL_C(Z80* ctx) { ctx->LD_HL_R(0b001); } + static inline void LD_HL_D(Z80* ctx) { ctx->LD_HL_R(0b010); } + static inline void LD_HL_E(Z80* ctx) { ctx->LD_HL_R(0b011); } + static inline void LD_HL_H(Z80* ctx) { ctx->LD_HL_R(0b100); } + static inline void LD_HL_L(Z80* ctx) { ctx->LD_HL_R(0b101); } + static inline void LD_HL_A(Z80* ctx) { ctx->LD_HL_R(0b111); } + inline void LD_HL_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); unsigned short addr = getHL(); - if (isDebug()) log("[%04X] LD (%s), %s", reg.PC, registerPairDump(0b10), registerDump(r)); + if (isDebug()) log("[%04X] LD (%s), %s", reg.PC - 1, registerPairDump(0b10), registerDump(r)); writeByte(addr, *rp, 3); - reg.PC += 1; - return 0; } // Load location (IX+d) with Reg. r - static inline int LD_IX_A(Z80* ctx) { return ctx->LD_IX_R(0b111); } - static inline int LD_IX_B(Z80* ctx) { return ctx->LD_IX_R(0b000); } - static inline int LD_IX_C(Z80* ctx) { return ctx->LD_IX_R(0b001); } - static inline int LD_IX_D(Z80* ctx) { return ctx->LD_IX_R(0b010); } - static inline int LD_IX_E(Z80* ctx) { return ctx->LD_IX_R(0b011); } - static inline int LD_IX_H(Z80* ctx) { return ctx->LD_IX_R(0b100); } - static inline int LD_IX_L(Z80* ctx) { return ctx->LD_IX_R(0b101); } - inline int LD_IX_R(unsigned char r) + static inline void LD_IX_A(Z80* ctx) { ctx->LD_IX_R(0b111); } + static inline void LD_IX_B(Z80* ctx) { ctx->LD_IX_R(0b000); } + static inline void LD_IX_C(Z80* ctx) { ctx->LD_IX_R(0b001); } + static inline void LD_IX_D(Z80* ctx) { ctx->LD_IX_R(0b010); } + static inline void LD_IX_E(Z80* ctx) { ctx->LD_IX_R(0b011); } + static inline void LD_IX_H(Z80* ctx) { ctx->LD_IX_R(0b100); } + static inline void LD_IX_L(Z80* ctx) { ctx->LD_IX_R(0b101); } + inline void LD_IX_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IX + d); - if (isDebug()) log("[%04X] LD (IX<$%04X>+$%02X), %s", reg.PC, reg.IX, d, registerDump(r)); + if (isDebug()) log("[%04X] LD (IX<$%04X>+$%02X), %s", reg.PC - 3, reg.IX, d, registerDump(r)); if (rp) writeByte(addr, *rp); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Load location (IY+d) with Reg. r - static inline int LD_IY_A(Z80* ctx) { return ctx->LD_IY_R(0b111); } - static inline int LD_IY_B(Z80* ctx) { return ctx->LD_IY_R(0b000); } - static inline int LD_IY_C(Z80* ctx) { return ctx->LD_IY_R(0b001); } - static inline int LD_IY_D(Z80* ctx) { return ctx->LD_IY_R(0b010); } - static inline int LD_IY_E(Z80* ctx) { return ctx->LD_IY_R(0b011); } - static inline int LD_IY_H(Z80* ctx) { return ctx->LD_IY_R(0b100); } - static inline int LD_IY_L(Z80* ctx) { return ctx->LD_IY_R(0b101); } - inline int LD_IY_R(unsigned char r) + static inline void LD_IY_A(Z80* ctx) { ctx->LD_IY_R(0b111); } + static inline void LD_IY_B(Z80* ctx) { ctx->LD_IY_R(0b000); } + static inline void LD_IY_C(Z80* ctx) { ctx->LD_IY_R(0b001); } + static inline void LD_IY_D(Z80* ctx) { ctx->LD_IY_R(0b010); } + static inline void LD_IY_E(Z80* ctx) { ctx->LD_IY_R(0b011); } + static inline void LD_IY_H(Z80* ctx) { ctx->LD_IY_R(0b100); } + static inline void LD_IY_L(Z80* ctx) { ctx->LD_IY_R(0b101); } + inline void LD_IY_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IY + d); - if (isDebug()) log("[%04X] LD (IY<$%04X>+$%02X), %s", reg.PC, reg.IY, d, registerDump(r)); + if (isDebug()) log("[%04X] LD (IY<$%04X>+$%02X), %s", reg.PC - 3, reg.IY, d, registerDump(r)); if (rp) writeByte(addr, *rp); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Load location (IX+d) with value n - static inline int LD_IX_N_(Z80* ctx) { return ctx->LD_IX_N(); } - inline int LD_IX_N() + static inline void LD_IX_N_(Z80* ctx) { ctx->LD_IX_N(); } + inline void LD_IX_N() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned char n = readByte(reg.PC + 3); + signed char d = (signed char)fetch(4); + unsigned char n = fetch(4); unsigned short addr = (unsigned short)(reg.IX + d); - if (isDebug()) log("[%04X] LD (IX<$%04X>+$%02X), $%02X", reg.PC, reg.IX, d, n); writeByte(addr, n, 3); - reg.PC += 4; - return 0; + if (isDebug()) log("[%04X] LD (IX<$%04X>+$%02X), $%02X", reg.PC - 4, reg.IX, d, n); } // Load location (IY+d) with value n - static inline int LD_IY_N_(Z80* ctx) { return ctx->LD_IY_N(); } - inline int LD_IY_N() + static inline void LD_IY_N_(Z80* ctx) { ctx->LD_IY_N(); } + inline void LD_IY_N() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned char n = readByte(reg.PC + 3); + signed char d = (signed char)fetch(4); + unsigned char n = fetch(4); unsigned short addr = (unsigned short)(reg.IY + d); - if (isDebug()) log("[%04X] LD (IY<$%04X>+$%02X), $%02X", reg.PC, reg.IY, d, n); writeByte(addr, n, 3); - reg.PC += 4; - return 0; + if (isDebug()) log("[%04X] LD (IY<$%04X>+$%02X), $%02X", reg.PC - 4, reg.IY, d, n); } // Load Reg. pair rp with value nn. - static inline int LD_BC_NN(Z80* ctx) { return ctx->LD_RP_NN(0b00); } - static inline int LD_DE_NN(Z80* ctx) { return ctx->LD_RP_NN(0b01); } - static inline int LD_HL_NN(Z80* ctx) { return ctx->LD_RP_NN(0b10); } - static inline int LD_SP_NN(Z80* ctx) { return ctx->LD_RP_NN(0b11); } - inline int LD_RP_NN(unsigned char rp) - { - unsigned char nL = readByte(reg.PC + 1, 3); - unsigned char nH = readByte(reg.PC + 2, 3); + static inline void LD_BC_NN(Z80* ctx) { ctx->LD_RP_NN(0b00); } + static inline void LD_DE_NN(Z80* ctx) { ctx->LD_RP_NN(0b01); } + static inline void LD_HL_NN(Z80* ctx) { ctx->LD_RP_NN(0b10); } + static inline void LD_SP_NN(Z80* ctx) { ctx->LD_RP_NN(0b11); } + inline void LD_RP_NN(unsigned char rp) + { unsigned char* rH; unsigned char* rL; switch (rp) { @@ -1525,96 +1401,99 @@ class Z80 rH = ®.pair.H; rL = ®.pair.L; break; - case 0b11: + case 0b11: { // SP is not managed in pair structure, so calculate directly - if (isDebug()) log("[%04X] LD SP<$%04X>, $%02X%02X", reg.PC, reg.SP, nH, nL); - reg.SP = (nH << 8) + nL; - reg.PC += 3; - return 0; + unsigned short sp = reg.SP; + setSPL(fetch(3)); + setSPH(fetch(3)); + if (isDebug()) log("[%04X] LD SP<$%04X>, $%04X", reg.PC - 3, sp, reg.SP); + return; + } default: if (isDebug()) log("invalid register pair has specified: $%02X", rp); - return -1; + throw std::runtime_error("invalid register pair has specified"); + return; } - if (isDebug()) log("[%04X] LD %s, $%02X%02X", reg.PC, registerPairDump(rp), nH, nL); - *rH = nH; + const char* dump = isDebug() ? registerPairDump(rp) : ""; + unsigned char nL = fetch(3); *rL = nL; - reg.PC += 3; - return 0; + unsigned char nH = fetch(3); + *rH = nH; + if (isDebug()) log("[%04X] LD %s, $%02X%02X", reg.PC - 3, dump, nH, nL); } - static inline int LD_IX_NN_(Z80* ctx) { return ctx->LD_IX_NN(); } - inline int LD_IX_NN() + static inline void LD_IX_NN_(Z80* ctx) { ctx->LD_IX_NN(); } + inline void LD_IX_NN() { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - if (isDebug()) log("[%04X] LD IX, $%02X%02X", reg.PC, nH, nL); - reg.IX = (nH << 8) + nL; - reg.PC += 4; - return 0; + setIXL(fetch(3)); + setIXH(fetch(3)); + if (isDebug()) log("[%04X] LD IX, $%04X", reg.PC - 4, reg.IX); } - static inline int LD_IY_NN_(Z80* ctx) { return ctx->LD_IY_NN(); } - inline int LD_IY_NN() + static inline void LD_IY_NN_(Z80* ctx) { ctx->LD_IY_NN(); } + inline void LD_IY_NN() { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - if (isDebug()) log("[%04X] LD IY, $%02X%02X", reg.PC, nH, nL); - reg.IY = (nH << 8) + nL; - reg.PC += 4; - return 0; + setIYL(fetch(3)); + setIYH(fetch(3)); + if (isDebug()) log("[%04X] LD IY, $%04X", reg.PC - 4, reg.IY); } // Load Reg. pair rp with location (nn) - static inline int LD_RP_ADDR_BC(Z80* ctx) { return ctx->LD_RP_ADDR(0b00); } - static inline int LD_RP_ADDR_DE(Z80* ctx) { return ctx->LD_RP_ADDR(0b01); } - static inline int LD_RP_ADDR_HL(Z80* ctx) { return ctx->LD_RP_ADDR(0b10); } - static inline int LD_RP_ADDR_SP(Z80* ctx) { return ctx->LD_RP_ADDR(0b11); } - inline int LD_RP_ADDR(unsigned char rp) - { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - unsigned short addr = (nH << 8) + nL; - unsigned char l = readByte(addr, 3); - unsigned char h = readByte(addr + 1, 3); - reg.WZ = addr + 1; - if (isDebug()) log("[%04X] LD %s, ($%02X%02X) = $%02X%02X", reg.PC, registerPairDump(rp), nH, nL, h, l); + static inline void LD_RP_ADDR_BC(Z80* ctx) { ctx->LD_RP_ADDR(0b00); } + static inline void LD_RP_ADDR_DE(Z80* ctx) { ctx->LD_RP_ADDR(0b01); } + static inline void LD_RP_ADDR_HL(Z80* ctx) { ctx->LD_RP_ADDR(0b10); } + static inline void LD_RP_ADDR_SP(Z80* ctx) { ctx->LD_RP_ADDR(0b11); } + inline void LD_RP_ADDR(unsigned char rp) + { + unsigned char l = fetch(3); + unsigned char h = fetch(3); + unsigned short addr = make16BitsFromLE(l, h); + unsigned char* rL; + unsigned char* rH; switch (rp) { - case 0b00: - reg.pair.B = h; - reg.pair.C = l; - break; - case 0b01: - reg.pair.D = h; - reg.pair.E = l; + case 0: + rH = ®.pair.B; + rL = ®.pair.C; break; - case 0b10: - reg.pair.H = h; - reg.pair.L = l; + case 1: + rH = ®.pair.D; + rL = ®.pair.E; break; - case 0b11: - reg.SP = (h << 8) + l; + case 2: + rH = ®.pair.H; + rL = ®.pair.L; break; + case 3: { + const char* dump = isDebug() ? registerPairDump(rp) : ""; + setSPL(readByte(addr, 3)); + setSPH(readByte(addr + 1, 3)); + reg.WZ = addr + 1; + if (isDebug()) log("[%04X] LD %s, ($%04X) = $%04X", reg.PC - 4, dump, addr, reg.SP); + return; + } default: if (isDebug()) log("invalid register pair has specified: $%02X", rp); - return -1; + throw std::runtime_error("invalid register pair has specified"); + return; } - reg.PC += 4; - return 0; + const char* dump = isDebug() ? registerPairDump(rp) : ""; + *rL = readByte(addr, 3); + *rH = readByte(addr + 1, 3); + reg.WZ = addr + 1; + if (isDebug()) log("[%04X] LD %s, ($%04X) = $%04X", reg.PC - 4, dump, addr, make16BitsFromLE(*rL, *rH)); } // Load location (nn) with Reg. pair rp. - static inline int LD_ADDR_RP_BC(Z80* ctx) { return ctx->LD_ADDR_RP(0b00); } - static inline int LD_ADDR_RP_DE(Z80* ctx) { return ctx->LD_ADDR_RP(0b01); } - static inline int LD_ADDR_RP_HL(Z80* ctx) { return ctx->LD_ADDR_RP(0b10); } - static inline int LD_ADDR_RP_SP(Z80* ctx) { return ctx->LD_ADDR_RP(0b11); } - inline int LD_ADDR_RP(unsigned char rp) - { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] LD ($%04X), %s", reg.PC, addr, registerPairDump(rp)); - unsigned char l; - unsigned char h; + static inline void LD_ADDR_RP_BC(Z80* ctx) { ctx->LD_ADDR_RP(0b00); } + static inline void LD_ADDR_RP_DE(Z80* ctx) { ctx->LD_ADDR_RP(0b01); } + static inline void LD_ADDR_RP_HL(Z80* ctx) { ctx->LD_ADDR_RP(0b10); } + static inline void LD_ADDR_RP_SP(Z80* ctx) { ctx->LD_ADDR_RP(0b11); } + inline void LD_ADDR_RP(unsigned char rp) + { + unsigned char l = fetch(3); + unsigned char h = fetch(3); + unsigned short addr = make16BitsFromLE(l, h); + if (isDebug()) log("[%04X] LD ($%04X), %s", reg.PC - 4, addr, registerPairDump(rp)); switch (rp) { case 0b00: h = reg.pair.B; @@ -1629,110 +1508,92 @@ class Z80 l = reg.pair.L; break; case 0b11: - h = (reg.SP & 0xFF00) >> 8; - l = reg.SP & 0x00FF; + splitTo8BitsPair(reg.SP, &h, &l); break; default: if (isDebug()) log("invalid register pair has specified: $%02X", rp); - return -1; + throw std::runtime_error("invalid register pair has specified"); + return; } writeByte(addr, l, 3); writeByte(addr + 1, h, 3); reg.WZ = addr + 1; - reg.PC += 4; - return 0; } // Load IX with location (nn) - static inline int LD_IX_ADDR_(Z80* ctx) { return ctx->LD_IX_ADDR(); } - inline int LD_IX_ADDR() + static inline void LD_IX_ADDR_(Z80* ctx) { ctx->LD_IX_ADDR(); } + inline void LD_IX_ADDR() { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - unsigned short addr = (nH << 8) + nL; - unsigned char l = readByte(addr, 3); - unsigned char h = readByte(addr + 1, 3); - if (isDebug()) log("[%04X] LD IX<$%04X>, ($%02X%02X) = $%02X%02X", reg.PC, reg.IX, nH, nL, h, l); - reg.IX = (h << 8) + l; - reg.PC += 4; - return 0; + unsigned char l = fetch(3); + unsigned char h = fetch(3); + unsigned short addr = make16BitsFromLE(l, h); + unsigned short ix = reg.IX; + setIXL(readByte(addr, 3)); + setIXH(readByte(addr + 1, 3)); + if (isDebug()) log("[%04X] LD IX<$%04X>, ($%04X) = $%04X", reg.PC - 4, ix, addr, reg.IX); } // Load IY with location (nn) - static inline int LD_IY_ADDR_(Z80* ctx) { return ctx->LD_IY_ADDR(); } - inline int LD_IY_ADDR() - { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - unsigned short addr = (nH << 8) + nL; - unsigned char l = readByte(addr, 3); - unsigned char h = readByte(addr + 1, 3); - if (isDebug()) log("[%04X] LD IY<$%04X>, ($%02X%02X) = $%02X%02X", reg.PC, reg.IY, nH, nL, h, l); - reg.IY = (h << 8) + l; - reg.PC += 4; - return 0; - } - - static inline int LD_ADDR_IX_(Z80* ctx) { return ctx->LD_ADDR_IX(); } - inline int LD_ADDR_IX() - { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] LD ($%04X), IX<$%04X>", reg.PC, addr, reg.IX); - unsigned char l = reg.IX & 0x00FF; - unsigned char h = (reg.IX & 0xFF00) >> 8; - writeByte(addr, l, 3); - writeByte(addr + 1, h, 3); - reg.PC += 4; - return 0; + static inline void LD_IY_ADDR_(Z80* ctx) { ctx->LD_IY_ADDR(); } + inline void LD_IY_ADDR() + { + unsigned char l = fetch(3); + unsigned char h = fetch(3); + unsigned short addr = make16BitsFromLE(l, h); + unsigned short iy = reg.IY; + setIYL(readByte(addr, 3)); + setIYH(readByte(addr + 1, 3)); + if (isDebug()) log("[%04X] LD IY<$%04X>, ($%04X) = $%04X", reg.PC - 4, iy, addr, reg.IY); } - static inline int LD_ADDR_IY_(Z80* ctx) { return ctx->LD_ADDR_IY(); } - inline int LD_ADDR_IY() + static inline void LD_ADDR_IX_(Z80* ctx) { ctx->LD_ADDR_IX(); } + inline void LD_ADDR_IX() { - unsigned char nL = readByte(reg.PC + 2, 3); - unsigned char nH = readByte(reg.PC + 3, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] LD ($%04X), IY<$%04X>", reg.PC, addr, reg.IY); - unsigned char l = reg.IY & 0x00FF; - unsigned char h = (reg.IY & 0xFF00) >> 8; - writeByte(addr, l, 3); - writeByte(addr + 1, h, 3); - reg.PC += 4; - return 0; + unsigned char l = fetch(3); + unsigned char h = fetch(3); + unsigned short addr = make16BitsFromLE(l, h); + if (isDebug()) log("[%04X] LD ($%04X), IX<$%04X>", reg.PC - 4, addr, reg.IX); + writeByte(addr, getIXL(), 3); + writeByte(addr + 1, getIXH(), 3); + } + + static inline void LD_ADDR_IY_(Z80* ctx) { ctx->LD_ADDR_IY(); } + inline void LD_ADDR_IY() + { + unsigned char l = fetch(3); + unsigned char h = fetch(3); + unsigned short addr = make16BitsFromLE(l, h); + if (isDebug()) log("[%04X] LD ($%04X), IY<$%04X>", reg.PC - 4, addr, reg.IY); + writeByte(addr, getIYL(), 3); + writeByte(addr + 1, getIYH(), 3); } // Load SP with IX. - static inline int LD_SP_IX_(Z80* ctx) { return ctx->LD_SP_IX(); } - inline int LD_SP_IX() + static inline void LD_SP_IX_(Z80* ctx) { ctx->LD_SP_IX(); } + inline void LD_SP_IX() { - unsigned short value = reg.IX; - if (isDebug()) log("[%04X] LD %s, IX<$%04X>", reg.PC, registerPairDump(0b11), value); - reg.SP = value; - reg.PC += 2; - return consumeClock(2); + if (isDebug()) log("[%04X] LD %s, IX<$%04X>", reg.PC - 2, registerPairDump(0b11), reg.IX); + reg.SP = reg.IX; + consumeClock(2); } // Load SP with IY. - static inline int LD_SP_IY_(Z80* ctx) { return ctx->LD_SP_IY(); } - inline int LD_SP_IY() + static inline void LD_SP_IY_(Z80* ctx) { ctx->LD_SP_IY(); } + inline void LD_SP_IY() { - unsigned short value = reg.IY; - if (isDebug()) log("[%04X] LD %s, IY<$%04X>", reg.PC, registerPairDump(0b11), value); - reg.SP = value; - reg.PC += 2; - return consumeClock(2); + if (isDebug()) log("[%04X] LD %s, IY<$%04X>", reg.PC - 2, registerPairDump(0b11), reg.IY); + reg.SP = reg.IY; + consumeClock(2); } // Load location (DE) with Loacation (HL), increment/decrement DE, HL, decrement BC - inline int repeatLD(bool isIncDEHL, bool isRepeat) + inline void repeatLD(bool isIncDEHL, bool isRepeat) { if (isDebug()) { if (isIncDEHL) { - if (isDebug()) log("[%04X] %s ... %s, %s, %s", reg.PC, isRepeat ? "LDIR" : "LDI", registerPairDump(0b00), registerPairDump(0b01), registerPairDump(0b10)); + if (isDebug()) log("[%04X] %s ... %s, %s, %s", reg.PC - 2, isRepeat ? "LDIR" : "LDI", registerPairDump(0b00), registerPairDump(0b01), registerPairDump(0b10)); } else { - if (isDebug()) log("[%04X] %s ... %s, %s, %s", reg.PC, isRepeat ? "LDDR" : "LDD", registerPairDump(0b00), registerPairDump(0b01), registerPairDump(0b10)); + if (isDebug()) log("[%04X] %s ... %s, %s, %s", reg.PC - 2, isRepeat ? "LDDR" : "LDD", registerPairDump(0b00), registerPairDump(0b01), registerPairDump(0b10)); } } unsigned short bc = getBC(); @@ -1758,166 +1619,138 @@ class Z80 setFlagY(an & 0b00000010); setFlagX(an & 0b00001000); if (isRepeat && 0 != bc) { + reg.PC -= 2; consumeClock(5); - } else { - reg.PC += 2; } - return 0; } - static inline int LDI(Z80* ctx) { return ctx->repeatLD(true, false); } - static inline int LDIR(Z80* ctx) { return ctx->repeatLD(true, true); } - static inline int LDD(Z80* ctx) { return ctx->repeatLD(false, false); } - static inline int LDDR(Z80* ctx) { return ctx->repeatLD(false, true); } + static inline void LDI(Z80* ctx) { ctx->repeatLD(true, false); } + static inline void LDIR(Z80* ctx) { ctx->repeatLD(true, true); } + static inline void LDD(Z80* ctx) { ctx->repeatLD(false, false); } + static inline void LDDR(Z80* ctx) { ctx->repeatLD(false, true); } // Exchange stack top with IX - static inline int EX_SP_IX_(Z80* ctx) { return ctx->EX_SP_IX(); } - inline int EX_SP_IX() + static inline void EX_SP_IX_(Z80* ctx) { ctx->EX_SP_IX(); } + inline void EX_SP_IX() { - unsigned char l = readByte(reg.SP); - unsigned char h = readByte(reg.SP + 1); - unsigned char i = (reg.IX & 0xFF00) >> 8; - unsigned char x = reg.IX & 0x00FF; - if (isDebug()) log("[%04X] EX (SP<$%04X>) = $%02X%02X, IX<$%04X>", reg.PC, reg.SP, h, l, reg.IX); - writeByte(reg.SP, x); - writeByte(reg.SP + 1, i, 3); - reg.IX = (h << 8) + l; - reg.PC += 2; - return 0; + unsigned short sp = reg.SP; + unsigned char l = pop(4); + unsigned char h = pop(4); + if (isDebug()) log("[%04X] EX (SP<$%04X>) = $%02X%02X, IX<$%04X>", reg.PC - 2, sp, h, l, reg.IX); + push(getIXH(), 4); + setIXH(h); + push(getIXL(), 3); + setIXL(l); } // Exchange stack top with IY - static inline int EX_SP_IY_(Z80* ctx) { return ctx->EX_SP_IY(); } - inline int EX_SP_IY() + static inline void EX_SP_IY_(Z80* ctx) { ctx->EX_SP_IY(); } + inline void EX_SP_IY() { - unsigned char l = readByte(reg.SP); - unsigned char h = readByte(reg.SP + 1); - unsigned char i = (reg.IY & 0xFF00) >> 8; - unsigned char y = reg.IY & 0x00FF; - if (isDebug()) log("[%04X] EX (SP<$%04X>) = $%02X%02X, IY<$%04X>", reg.PC, reg.SP, h, l, reg.IY); - writeByte(reg.SP, y); - writeByte(reg.SP + 1, i, 3); - reg.IY = (h << 8) + l; - reg.PC += 2; - return 0; + unsigned short sp = reg.SP; + unsigned char l = pop(4); + unsigned char h = pop(4); + if (isDebug()) log("[%04X] EX (SP<$%04X>) = $%02X%02X, IY<$%04X>", reg.PC - 2, sp, h, l, reg.IY); + push(getIYH(), 4); + setIYH(h); + push(getIYL(), 3); + setIYL(l); } // Push Reg. on Stack. - static inline int PUSH_BC(Z80* ctx) { return ctx->PUSH_RP(0b00); } - static inline int PUSH_DE(Z80* ctx) { return ctx->PUSH_RP(0b01); } - static inline int PUSH_HL(Z80* ctx) { return ctx->PUSH_RP(0b10); } - inline int PUSH_RP(unsigned char rp) - { - if (isDebug()) log("[%04X] PUSH %s ", reg.PC, registerPairDump(rp), reg.SP); - unsigned char l; - unsigned char h; + static inline void PUSH_BC(Z80* ctx) { ctx->PUSH_RP(0b00); } + static inline void PUSH_DE(Z80* ctx) { ctx->PUSH_RP(0b01); } + static inline void PUSH_HL(Z80* ctx) { ctx->PUSH_RP(0b10); } + inline void PUSH_RP(unsigned char rp) + { + if (isDebug()) log("[%04X] PUSH %s ", reg.PC - 1, registerPairDump(rp), reg.SP); switch (rp) { case 0b00: - h = reg.pair.B; - l = reg.pair.C; + push(reg.pair.B, 4); + push(reg.pair.C, 3); break; case 0b01: - h = reg.pair.D; - l = reg.pair.E; + push(reg.pair.D, 4); + push(reg.pair.E, 3); break; case 0b10: - h = reg.pair.H; - l = reg.pair.L; + push(reg.pair.H, 4); + push(reg.pair.L, 3); break; default: if (isDebug()) log("invalid register pair has specified: $%02X", rp); - return -1; + throw std::runtime_error("invalid register pair has specified"); } - writeByte(--reg.SP, h); - writeByte(--reg.SP, l, 3); - reg.PC++; - return 0; } // Push Reg. on Stack. - static inline int POP_BC(Z80* ctx) { return ctx->POP_RP(0b00); } - static inline int POP_DE(Z80* ctx) { return ctx->POP_RP(0b01); } - static inline int POP_HL(Z80* ctx) { return ctx->POP_RP(0b10); } - inline int POP_RP(unsigned char rp) + static inline void POP_BC(Z80* ctx) { ctx->POP_RP(0b00); } + static inline void POP_DE(Z80* ctx) { ctx->POP_RP(0b01); } + static inline void POP_HL(Z80* ctx) { ctx->POP_RP(0b10); } + inline void POP_RP(unsigned char rp) { unsigned short sp = reg.SP; - unsigned char* l; - unsigned char* h; + const char* dump = isDebug() ? registerPairDump(rp) : ""; + unsigned short after; switch (rp) { case 0b00: - h = ®.pair.B; - l = ®.pair.C; + reg.pair.C = pop(3); + reg.pair.B = pop(3); + after = getBC(); break; case 0b01: - h = ®.pair.D; - l = ®.pair.E; + reg.pair.E = pop(3); + reg.pair.D = pop(3); + after = getDE(); break; case 0b10: - h = ®.pair.H; - l = ®.pair.L; + reg.pair.L = pop(3); + reg.pair.H = pop(3); + after = getHL(); break; default: if (isDebug()) log("invalid register pair has specified: $%02X", rp); - return -1; + throw std::runtime_error("invalid register pair has specified"); + return; } - unsigned char lm = readByte(reg.SP++, 3); - unsigned char hm = readByte(reg.SP++, 3); - if (isDebug()) log("[%04X] POP %s = $%02X%02X", reg.PC, registerPairDump(rp), sp, hm, lm); - *l = lm; - *h = hm; - reg.PC++; - return 0; + if (isDebug()) log("[%04X] POP %s = $%04X", reg.PC - 1, dump, sp, after); } // Push Reg. IX on Stack. - static inline int PUSH_IX_(Z80* ctx) { return ctx->PUSH_IX(); } - inline int PUSH_IX() + static inline void PUSH_IX_(Z80* ctx) { ctx->PUSH_IX(); } + inline void PUSH_IX() { - if (isDebug()) log("[%04X] PUSH IX<$%04X> ", reg.PC, reg.IX, reg.SP); - unsigned char h = (reg.IX & 0xFF00) >> 8; - unsigned char l = reg.IX & 0x00FF; - writeByte(--reg.SP, h); - writeByte(--reg.SP, l, 3); - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] PUSH IX<$%04X> ", reg.PC - 2, reg.IX, reg.SP); + push(getIXH(), 4); + push(getIXL(), 3); } // Pop Reg. IX from Stack. - static inline int POP_IX_(Z80* ctx) { return ctx->POP_IX(); } - inline int POP_IX() + static inline void POP_IX_(Z80* ctx) { ctx->POP_IX(); } + inline void POP_IX() { unsigned short sp = reg.SP; - unsigned char l = readByte(reg.SP++, 3); - unsigned char h = readByte(reg.SP++, 3); - if (isDebug()) log("[%04X] POP IX = $%02X%02X", reg.PC, sp, h, l); - reg.IX = (h << 8) + l; - reg.PC += 2; - return 0; + setIXL(pop(3)); + setIXH(pop(3)); + if (isDebug()) log("[%04X] POP IX = $%04X", reg.PC - 2, sp, reg.IX); } // Push Reg. IY on Stack. - static inline int PUSH_IY_(Z80* ctx) { return ctx->PUSH_IY(); } - inline int PUSH_IY() + static inline void PUSH_IY_(Z80* ctx) { ctx->PUSH_IY(); } + inline void PUSH_IY() { - if (isDebug()) log("[%04X] PUSH IY<$%04X> ", reg.PC, reg.IY, reg.SP); - unsigned char h = (reg.IY & 0xFF00) >> 8; - unsigned char l = reg.IY & 0x00FF; - writeByte(--reg.SP, h); - writeByte(--reg.SP, l, 3); - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] PUSH IY<$%04X> ", reg.PC - 2, reg.IY, reg.SP); + push(getIYH(), 4); + push(getIYL(), 3); } // Pop Reg. IY from Stack. - static inline int POP_IY_(Z80* ctx) { return ctx->POP_IY(); } - inline int POP_IY() + static inline void POP_IY_(Z80* ctx) { ctx->POP_IY(); } + inline void POP_IY() { unsigned short sp = reg.SP; - unsigned char l = readByte(reg.SP++, 3); - unsigned char h = readByte(reg.SP++, 3); - if (isDebug()) log("[%04X] POP IY = $%02X%02X", reg.PC, sp, h, l); - reg.IY = (h << 8) + l; - reg.PC += 2; - return 0; + setIYL(pop(3)); + setIYH(pop(3)); + if (isDebug()) log("[%04X] POP IY = $%04X", reg.PC - 2, sp, reg.IY); } inline void setFlagByRotate(unsigned char n, bool carry, bool isA = false) @@ -2012,293 +1845,251 @@ class Z80 return n; } - static inline int RLCA(Z80* ctx) + static inline void RLCA(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] RLCA ", ctx->reg.PC, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] RLCA ", ctx->reg.PC - 1, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); ctx->reg.pair.A = ctx->RLC(ctx->reg.pair.A, true); - ctx->reg.PC++; - return 0; } - static inline int RRCA(Z80* ctx) + static inline void RRCA(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] RRCA ", ctx->reg.PC, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] RRCA ", ctx->reg.PC - 1, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); ctx->reg.pair.A = ctx->RRC(ctx->reg.pair.A, true); - ctx->reg.PC++; - return 0; } - static inline int RLA(Z80* ctx) + static inline void RLA(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] RLA ", ctx->reg.PC, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] RLA ", ctx->reg.PC - 1, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); ctx->reg.pair.A = ctx->RL(ctx->reg.pair.A, true); - ctx->reg.PC++; - return 0; } - static inline int RRA(Z80* ctx) + static inline void RRA(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] RRA ", ctx->reg.PC, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] RRA ", ctx->reg.PC - 1, ctx->reg.pair.A, ctx->isFlagC() ? "ON" : "OFF"); ctx->reg.pair.A = ctx->RR(ctx->reg.pair.A, true); - ctx->reg.PC++; - return 0; } // Rotate register Left Circular - static inline int RLC_B(Z80* ctx) { return ctx->RLC_R(0b000); } - static inline int RLC_C(Z80* ctx) { return ctx->RLC_R(0b001); } - static inline int RLC_D(Z80* ctx) { return ctx->RLC_R(0b010); } - static inline int RLC_E(Z80* ctx) { return ctx->RLC_R(0b011); } - static inline int RLC_H(Z80* ctx) { return ctx->RLC_R(0b100); } - static inline int RLC_L(Z80* ctx) { return ctx->RLC_R(0b101); } - static inline int RLC_A(Z80* ctx) { return ctx->RLC_R(0b111); } - inline int RLC_R(unsigned char r) + static inline void RLC_B(Z80* ctx) { ctx->RLC_R(0b000); } + static inline void RLC_C(Z80* ctx) { ctx->RLC_R(0b001); } + static inline void RLC_D(Z80* ctx) { ctx->RLC_R(0b010); } + static inline void RLC_E(Z80* ctx) { ctx->RLC_R(0b011); } + static inline void RLC_H(Z80* ctx) { ctx->RLC_R(0b100); } + static inline void RLC_L(Z80* ctx) { ctx->RLC_R(0b101); } + static inline void RLC_A(Z80* ctx) { ctx->RLC_R(0b111); } + inline void RLC_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] RLC %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] RLC %s", reg.PC - 2, registerDump(r)); *rp = RLC(*rp); - reg.PC += 2; - return 0; } // Rotate Left register - static inline int RL_B(Z80* ctx) { return ctx->RL_R(0b000); } - static inline int RL_C(Z80* ctx) { return ctx->RL_R(0b001); } - static inline int RL_D(Z80* ctx) { return ctx->RL_R(0b010); } - static inline int RL_E(Z80* ctx) { return ctx->RL_R(0b011); } - static inline int RL_H(Z80* ctx) { return ctx->RL_R(0b100); } - static inline int RL_L(Z80* ctx) { return ctx->RL_R(0b101); } - static inline int RL_A(Z80* ctx) { return ctx->RL_R(0b111); } - inline int RL_R(unsigned char r) + static inline void RL_B(Z80* ctx) { ctx->RL_R(0b000); } + static inline void RL_C(Z80* ctx) { ctx->RL_R(0b001); } + static inline void RL_D(Z80* ctx) { ctx->RL_R(0b010); } + static inline void RL_E(Z80* ctx) { ctx->RL_R(0b011); } + static inline void RL_H(Z80* ctx) { ctx->RL_R(0b100); } + static inline void RL_L(Z80* ctx) { ctx->RL_R(0b101); } + static inline void RL_A(Z80* ctx) { ctx->RL_R(0b111); } + inline void RL_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] RL %s ", reg.PC, registerDump(r), isFlagC() ? "ON" : "OFF"); + if (isDebug()) log("[%04X] RL %s ", reg.PC - 2, registerDump(r), isFlagC() ? "ON" : "OFF"); *rp = RL(*rp); - reg.PC += 2; - return 0; } // Shift operand register left Arithmetic - static inline int SLA_B(Z80* ctx) { return ctx->SLA_R(0b000); } - static inline int SLA_C(Z80* ctx) { return ctx->SLA_R(0b001); } - static inline int SLA_D(Z80* ctx) { return ctx->SLA_R(0b010); } - static inline int SLA_E(Z80* ctx) { return ctx->SLA_R(0b011); } - static inline int SLA_H(Z80* ctx) { return ctx->SLA_R(0b100); } - static inline int SLA_L(Z80* ctx) { return ctx->SLA_R(0b101); } - static inline int SLA_A(Z80* ctx) { return ctx->SLA_R(0b111); } - inline int SLA_R(unsigned char r) + static inline void SLA_B(Z80* ctx) { ctx->SLA_R(0b000); } + static inline void SLA_C(Z80* ctx) { ctx->SLA_R(0b001); } + static inline void SLA_D(Z80* ctx) { ctx->SLA_R(0b010); } + static inline void SLA_E(Z80* ctx) { ctx->SLA_R(0b011); } + static inline void SLA_H(Z80* ctx) { ctx->SLA_R(0b100); } + static inline void SLA_L(Z80* ctx) { ctx->SLA_R(0b101); } + static inline void SLA_A(Z80* ctx) { ctx->SLA_R(0b111); } + inline void SLA_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] SLA %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] SLA %s", reg.PC - 2, registerDump(r)); *rp = SLA(*rp); - reg.PC += 2; - return 0; } // Rotate register Right Circular - static inline int RRC_B(Z80* ctx) { return ctx->RRC_R(0b000); } - static inline int RRC_C(Z80* ctx) { return ctx->RRC_R(0b001); } - static inline int RRC_D(Z80* ctx) { return ctx->RRC_R(0b010); } - static inline int RRC_E(Z80* ctx) { return ctx->RRC_R(0b011); } - static inline int RRC_H(Z80* ctx) { return ctx->RRC_R(0b100); } - static inline int RRC_L(Z80* ctx) { return ctx->RRC_R(0b101); } - static inline int RRC_A(Z80* ctx) { return ctx->RRC_R(0b111); } - inline int RRC_R(unsigned char r) + static inline void RRC_B(Z80* ctx) { ctx->RRC_R(0b000); } + static inline void RRC_C(Z80* ctx) { ctx->RRC_R(0b001); } + static inline void RRC_D(Z80* ctx) { ctx->RRC_R(0b010); } + static inline void RRC_E(Z80* ctx) { ctx->RRC_R(0b011); } + static inline void RRC_H(Z80* ctx) { ctx->RRC_R(0b100); } + static inline void RRC_L(Z80* ctx) { ctx->RRC_R(0b101); } + static inline void RRC_A(Z80* ctx) { ctx->RRC_R(0b111); } + inline void RRC_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] RRC %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] RRC %s", reg.PC - 2, registerDump(r)); *rp = RRC(*rp); - reg.PC += 2; - return 0; } // Rotate Right register - static inline int RR_B(Z80* ctx) { return ctx->RR_R(0b000); } - static inline int RR_C(Z80* ctx) { return ctx->RR_R(0b001); } - static inline int RR_D(Z80* ctx) { return ctx->RR_R(0b010); } - static inline int RR_E(Z80* ctx) { return ctx->RR_R(0b011); } - static inline int RR_H(Z80* ctx) { return ctx->RR_R(0b100); } - static inline int RR_L(Z80* ctx) { return ctx->RR_R(0b101); } - static inline int RR_A(Z80* ctx) { return ctx->RR_R(0b111); } - inline int RR_R(unsigned char r) + static inline void RR_B(Z80* ctx) { ctx->RR_R(0b000); } + static inline void RR_C(Z80* ctx) { ctx->RR_R(0b001); } + static inline void RR_D(Z80* ctx) { ctx->RR_R(0b010); } + static inline void RR_E(Z80* ctx) { ctx->RR_R(0b011); } + static inline void RR_H(Z80* ctx) { ctx->RR_R(0b100); } + static inline void RR_L(Z80* ctx) { ctx->RR_R(0b101); } + static inline void RR_A(Z80* ctx) { ctx->RR_R(0b111); } + inline void RR_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] RR %s ", reg.PC, registerDump(r), isFlagC() ? "ON" : "OFF"); + if (isDebug()) log("[%04X] RR %s ", reg.PC - 2, registerDump(r), isFlagC() ? "ON" : "OFF"); *rp = RR(*rp); - reg.PC += 2; - return 0; } // Shift operand register Right Arithmetic - static inline int SRA_B(Z80* ctx) { return ctx->SRA_R(0b000); } - static inline int SRA_C(Z80* ctx) { return ctx->SRA_R(0b001); } - static inline int SRA_D(Z80* ctx) { return ctx->SRA_R(0b010); } - static inline int SRA_E(Z80* ctx) { return ctx->SRA_R(0b011); } - static inline int SRA_H(Z80* ctx) { return ctx->SRA_R(0b100); } - static inline int SRA_L(Z80* ctx) { return ctx->SRA_R(0b101); } - static inline int SRA_A(Z80* ctx) { return ctx->SRA_R(0b111); } - inline int SRA_R(unsigned char r) + static inline void SRA_B(Z80* ctx) { ctx->SRA_R(0b000); } + static inline void SRA_C(Z80* ctx) { ctx->SRA_R(0b001); } + static inline void SRA_D(Z80* ctx) { ctx->SRA_R(0b010); } + static inline void SRA_E(Z80* ctx) { ctx->SRA_R(0b011); } + static inline void SRA_H(Z80* ctx) { ctx->SRA_R(0b100); } + static inline void SRA_L(Z80* ctx) { ctx->SRA_R(0b101); } + static inline void SRA_A(Z80* ctx) { ctx->SRA_R(0b111); } + inline void SRA_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] SRA %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] SRA %s", reg.PC - 2, registerDump(r)); *rp = SRA(*rp); - reg.PC += 2; - return 0; } // Shift operand register Right Logical - static inline int SRL_B(Z80* ctx) { return ctx->SRL_R(0b000); } - static inline int SRL_C(Z80* ctx) { return ctx->SRL_R(0b001); } - static inline int SRL_D(Z80* ctx) { return ctx->SRL_R(0b010); } - static inline int SRL_E(Z80* ctx) { return ctx->SRL_R(0b011); } - static inline int SRL_H(Z80* ctx) { return ctx->SRL_R(0b100); } - static inline int SRL_L(Z80* ctx) { return ctx->SRL_R(0b101); } - static inline int SRL_A(Z80* ctx) { return ctx->SRL_R(0b111); } - inline int SRL_R(unsigned char r) + static inline void SRL_B(Z80* ctx) { ctx->SRL_R(0b000); } + static inline void SRL_C(Z80* ctx) { ctx->SRL_R(0b001); } + static inline void SRL_D(Z80* ctx) { ctx->SRL_R(0b010); } + static inline void SRL_E(Z80* ctx) { ctx->SRL_R(0b011); } + static inline void SRL_H(Z80* ctx) { ctx->SRL_R(0b100); } + static inline void SRL_L(Z80* ctx) { ctx->SRL_R(0b101); } + static inline void SRL_A(Z80* ctx) { ctx->SRL_R(0b111); } + inline void SRL_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] SRL %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] SRL %s", reg.PC - 2, registerDump(r)); *rp = SRL(*rp); - reg.PC += 2; - return 0; } // Shift operand register Left Logical - static inline int SLL_B(Z80* ctx) { return ctx->SLL_R(0b000); } - static inline int SLL_C(Z80* ctx) { return ctx->SLL_R(0b001); } - static inline int SLL_D(Z80* ctx) { return ctx->SLL_R(0b010); } - static inline int SLL_E(Z80* ctx) { return ctx->SLL_R(0b011); } - static inline int SLL_H(Z80* ctx) { return ctx->SLL_R(0b100); } - static inline int SLL_L(Z80* ctx) { return ctx->SLL_R(0b101); } - static inline int SLL_A(Z80* ctx) { return ctx->SLL_R(0b111); } - inline int SLL_R(unsigned char r) + static inline void SLL_B(Z80* ctx) { ctx->SLL_R(0b000); } + static inline void SLL_C(Z80* ctx) { ctx->SLL_R(0b001); } + static inline void SLL_D(Z80* ctx) { ctx->SLL_R(0b010); } + static inline void SLL_E(Z80* ctx) { ctx->SLL_R(0b011); } + static inline void SLL_H(Z80* ctx) { ctx->SLL_R(0b100); } + static inline void SLL_L(Z80* ctx) { ctx->SLL_R(0b101); } + static inline void SLL_A(Z80* ctx) { ctx->SLL_R(0b111); } + inline void SLL_R(unsigned char r) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] SLL %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] SLL %s", reg.PC - 2, registerDump(r)); *rp = SLL(*rp); - reg.PC += 2; - return 0; } // Rotate memory (HL) Left Circular - static inline int RLC_HL_(Z80* ctx) { return ctx->RLC_HL(); } - inline int RLC_HL() + static inline void RLC_HL_(Z80* ctx) { ctx->RLC_HL(); } + inline void RLC_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RLC (HL<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] RLC (HL<$%04X>) = $%02X", reg.PC - 2, addr, n); writeByte(addr, RLC(n), 3); - reg.PC += 2; - return 0; } // Rotate Left memory - static inline int RL_HL_(Z80* ctx) { return ctx->RL_HL(); } - inline int RL_HL() + static inline void RL_HL_(Z80* ctx) { ctx->RL_HL(); } + inline void RL_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RL (HL<$%04X>) = $%02X ", reg.PC, addr, n, isFlagC() ? "ON" : "OFF"); + if (isDebug()) log("[%04X] RL (HL<$%04X>) = $%02X ", reg.PC - 2, addr, n, isFlagC() ? "ON" : "OFF"); writeByte(addr, RL(n), 3); - reg.PC += 2; - return 0; } // Shift operand location (HL) left Arithmetic - static inline int SLA_HL_(Z80* ctx) { return ctx->SLA_HL(); } - inline int SLA_HL() + static inline void SLA_HL_(Z80* ctx) { ctx->SLA_HL(); } + inline void SLA_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SLA (HL<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] SLA (HL<$%04X>) = $%02X", reg.PC - 2, addr, n); writeByte(addr, SLA(n), 3); - reg.PC += 2; - return 0; } // Rotate memory (HL) Right Circular - static inline int RRC_HL_(Z80* ctx) { return ctx->RRC_HL(); } - inline int RRC_HL() + static inline void RRC_HL_(Z80* ctx) { ctx->RRC_HL(); } + inline void RRC_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RRC (HL<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] RRC (HL<$%04X>) = $%02X", reg.PC - 2, addr, n); writeByte(addr, RRC(n), 3); - reg.PC += 2; - return 0; } // Rotate Right memory - static inline int RR_HL_(Z80* ctx) { return ctx->RR_HL(); } - inline int RR_HL() + static inline void RR_HL_(Z80* ctx) { ctx->RR_HL(); } + inline void RR_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RR (HL<$%04X>) = $%02X ", reg.PC, addr, n, isFlagC() ? "ON" : "OFF"); + if (isDebug()) log("[%04X] RR (HL<$%04X>) = $%02X ", reg.PC - 2, addr, n, isFlagC() ? "ON" : "OFF"); writeByte(addr, RR(n), 3); - reg.PC += 2; - return 0; } // Shift operand location (HL) Right Arithmetic - static inline int SRA_HL_(Z80* ctx) { return ctx->SRA_HL(); } - inline int SRA_HL() + static inline void SRA_HL_(Z80* ctx) { ctx->SRA_HL(); } + inline void SRA_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SRA (HL<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] SRA (HL<$%04X>) = $%02X", reg.PC - 2, addr, n); writeByte(addr, SRA(n), 3); - reg.PC += 2; - return 0; } // Shift operand location (HL) Right Logical - static inline int SRL_HL_(Z80* ctx) { return ctx->SRL_HL(); } - inline int SRL_HL() + static inline void SRL_HL_(Z80* ctx) { ctx->SRL_HL(); } + inline void SRL_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SRL (HL<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] SRL (HL<$%04X>) = $%02X", reg.PC - 2, addr, n); writeByte(addr, SRL(n), 3); - reg.PC += 2; - return 0; } // Shift operand location (HL) Left Logical - static inline int SLL_HL_(Z80* ctx) { return ctx->SLL_HL(); } - inline int SLL_HL() + static inline void SLL_HL_(Z80* ctx) { ctx->SLL_HL(); } + inline void SLL_HL() { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SLL (HL<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] SLL (HL<$%04X>) = $%02X", reg.PC - 2, addr, n); writeByte(addr, SLL(n), 3); - reg.PC += 2; - return 0; } // Rotate memory (IX+d) Left Circular - static inline int RLC_IX_(Z80* ctx, signed char d) { return ctx->RLC_IX(d); } - inline int RLC_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RLC_IX_(Z80* ctx, signed char d) { ctx->RLC_IX(d); } + inline void RLC_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RLC (IX+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RLC (IX+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = RLC(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Rotate memory (IX+d) Left Circular with load to Reg A/B/C/D/E/H/L/F - static inline int RLC_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->RLC_IX_with_LD(d, 0b000); } - static inline int RLC_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->RLC_IX_with_LD(d, 0b001); } - static inline int RLC_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->RLC_IX_with_LD(d, 0b010); } - static inline int RLC_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->RLC_IX_with_LD(d, 0b011); } - static inline int RLC_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->RLC_IX_with_LD(d, 0b100); } - static inline int RLC_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->RLC_IX_with_LD(d, 0b101); } - static inline int RLC_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->RLC_IX_with_LD(d, 0b111); } - inline int RLC_IX_with_LD(signed char d, unsigned char r) + static inline void RLC_IX_with_LD_B(Z80* ctx, signed char d) { ctx->RLC_IX_with_LD(d, 0b000); } + static inline void RLC_IX_with_LD_C(Z80* ctx, signed char d) { ctx->RLC_IX_with_LD(d, 0b001); } + static inline void RLC_IX_with_LD_D(Z80* ctx, signed char d) { ctx->RLC_IX_with_LD(d, 0b010); } + static inline void RLC_IX_with_LD_E(Z80* ctx, signed char d) { ctx->RLC_IX_with_LD(d, 0b011); } + static inline void RLC_IX_with_LD_H(Z80* ctx, signed char d) { ctx->RLC_IX_with_LD(d, 0b100); } + static inline void RLC_IX_with_LD_L(Z80* ctx, signed char d) { ctx->RLC_IX_with_LD(d, 0b101); } + static inline void RLC_IX_with_LD_A(Z80* ctx, signed char d) { ctx->RLC_IX_with_LD(d, 0b111); } + inline void RLC_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2307,18 +2098,18 @@ class Z80 } else { buf[0] = '\0'; } - return RLC_IX(d, rp, buf); + RLC_IX(d, rp, buf); } // Rotate memory (IY+d) Left Circular with load to Reg A/B/C/D/E/H/L/F - static inline int RLC_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->RLC_IY_with_LD(d, 0b000); } - static inline int RLC_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->RLC_IY_with_LD(d, 0b001); } - static inline int RLC_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->RLC_IY_with_LD(d, 0b010); } - static inline int RLC_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->RLC_IY_with_LD(d, 0b011); } - static inline int RLC_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->RLC_IY_with_LD(d, 0b100); } - static inline int RLC_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->RLC_IY_with_LD(d, 0b101); } - static inline int RLC_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->RLC_IY_with_LD(d, 0b111); } - inline int RLC_IY_with_LD(signed char d, unsigned char r) + static inline void RLC_IY_with_LD_B(Z80* ctx, signed char d) { ctx->RLC_IY_with_LD(d, 0b000); } + static inline void RLC_IY_with_LD_C(Z80* ctx, signed char d) { ctx->RLC_IY_with_LD(d, 0b001); } + static inline void RLC_IY_with_LD_D(Z80* ctx, signed char d) { ctx->RLC_IY_with_LD(d, 0b010); } + static inline void RLC_IY_with_LD_E(Z80* ctx, signed char d) { ctx->RLC_IY_with_LD(d, 0b011); } + static inline void RLC_IY_with_LD_H(Z80* ctx, signed char d) { ctx->RLC_IY_with_LD(d, 0b100); } + static inline void RLC_IY_with_LD_L(Z80* ctx, signed char d) { ctx->RLC_IY_with_LD(d, 0b101); } + static inline void RLC_IY_with_LD_A(Z80* ctx, signed char d) { ctx->RLC_IY_with_LD(d, 0b111); } + inline void RLC_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2327,32 +2118,30 @@ class Z80 } else { buf[0] = '\0'; } - return RLC_IY(d, rp, buf); + RLC_IY(d, rp, buf); } // Rotate memory (IX+d) Right Circular - static inline int RRC_IX_(Z80* ctx, signed char d) { return ctx->RRC_IX(d); } - inline int RRC_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RRC_IX_(Z80* ctx, signed char d) { ctx->RRC_IX(d); } + inline void RRC_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RRC (IX+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RRC (IX+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = RRC(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Rotate memory (IX+d) Right Circular with load to Reg A/B/C/D/E/H/L/F - static inline int RRC_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->RRC_IX_with_LD(d, 0b000); } - static inline int RRC_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->RRC_IX_with_LD(d, 0b001); } - static inline int RRC_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->RRC_IX_with_LD(d, 0b010); } - static inline int RRC_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->RRC_IX_with_LD(d, 0b011); } - static inline int RRC_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->RRC_IX_with_LD(d, 0b100); } - static inline int RRC_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->RRC_IX_with_LD(d, 0b101); } - static inline int RRC_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->RRC_IX_with_LD(d, 0b111); } - inline int RRC_IX_with_LD(signed char d, unsigned char r) + static inline void RRC_IX_with_LD_B(Z80* ctx, signed char d) { ctx->RRC_IX_with_LD(d, 0b000); } + static inline void RRC_IX_with_LD_C(Z80* ctx, signed char d) { ctx->RRC_IX_with_LD(d, 0b001); } + static inline void RRC_IX_with_LD_D(Z80* ctx, signed char d) { ctx->RRC_IX_with_LD(d, 0b010); } + static inline void RRC_IX_with_LD_E(Z80* ctx, signed char d) { ctx->RRC_IX_with_LD(d, 0b011); } + static inline void RRC_IX_with_LD_H(Z80* ctx, signed char d) { ctx->RRC_IX_with_LD(d, 0b100); } + static inline void RRC_IX_with_LD_L(Z80* ctx, signed char d) { ctx->RRC_IX_with_LD(d, 0b101); } + static inline void RRC_IX_with_LD_A(Z80* ctx, signed char d) { ctx->RRC_IX_with_LD(d, 0b111); } + inline void RRC_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2361,18 +2150,18 @@ class Z80 } else { buf[0] = '\0'; } - return RRC_IX(d, rp, buf); + RRC_IX(d, rp, buf); } // Rotate memory (IY+d) Right Circular with load to Reg A/B/C/D/E/H/L/F - static inline int RRC_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->RRC_IY_with_LD(d, 0b000); } - static inline int RRC_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->RRC_IY_with_LD(d, 0b001); } - static inline int RRC_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->RRC_IY_with_LD(d, 0b010); } - static inline int RRC_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->RRC_IY_with_LD(d, 0b011); } - static inline int RRC_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->RRC_IY_with_LD(d, 0b100); } - static inline int RRC_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->RRC_IY_with_LD(d, 0b101); } - static inline int RRC_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->RRC_IY_with_LD(d, 0b111); } - inline int RRC_IY_with_LD(signed char d, unsigned char r) + static inline void RRC_IY_with_LD_B(Z80* ctx, signed char d) { ctx->RRC_IY_with_LD(d, 0b000); } + static inline void RRC_IY_with_LD_C(Z80* ctx, signed char d) { ctx->RRC_IY_with_LD(d, 0b001); } + static inline void RRC_IY_with_LD_D(Z80* ctx, signed char d) { ctx->RRC_IY_with_LD(d, 0b010); } + static inline void RRC_IY_with_LD_E(Z80* ctx, signed char d) { ctx->RRC_IY_with_LD(d, 0b011); } + static inline void RRC_IY_with_LD_H(Z80* ctx, signed char d) { ctx->RRC_IY_with_LD(d, 0b100); } + static inline void RRC_IY_with_LD_L(Z80* ctx, signed char d) { ctx->RRC_IY_with_LD(d, 0b101); } + static inline void RRC_IY_with_LD_A(Z80* ctx, signed char d) { ctx->RRC_IY_with_LD(d, 0b111); } + inline void RRC_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2381,32 +2170,30 @@ class Z80 } else { buf[0] = '\0'; } - return RRC_IY(d, rp, buf); + RRC_IY(d, rp, buf); } // Rotate Left memory - static inline int RL_IX_(Z80* ctx, signed char d) { return ctx->RL_IX(d); } - inline int RL_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RL_IX_(Z80* ctx, signed char d) { ctx->RL_IX(d); } + inline void RL_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RL (IX+d<$%04X>) = $%02X %s", reg.PC, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RL (IX+d<$%04X>) = $%02X %s", reg.PC - 4, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); unsigned char result = RL(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Rotate Left memory with load Reg. - static inline int RL_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->RL_IX_with_LD(d, 0b000); } - static inline int RL_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->RL_IX_with_LD(d, 0b001); } - static inline int RL_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->RL_IX_with_LD(d, 0b010); } - static inline int RL_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->RL_IX_with_LD(d, 0b011); } - static inline int RL_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->RL_IX_with_LD(d, 0b100); } - static inline int RL_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->RL_IX_with_LD(d, 0b101); } - static inline int RL_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->RL_IX_with_LD(d, 0b111); } - inline int RL_IX_with_LD(signed char d, unsigned char r) + static inline void RL_IX_with_LD_B(Z80* ctx, signed char d) { ctx->RL_IX_with_LD(d, 0b000); } + static inline void RL_IX_with_LD_C(Z80* ctx, signed char d) { ctx->RL_IX_with_LD(d, 0b001); } + static inline void RL_IX_with_LD_D(Z80* ctx, signed char d) { ctx->RL_IX_with_LD(d, 0b010); } + static inline void RL_IX_with_LD_E(Z80* ctx, signed char d) { ctx->RL_IX_with_LD(d, 0b011); } + static inline void RL_IX_with_LD_H(Z80* ctx, signed char d) { ctx->RL_IX_with_LD(d, 0b100); } + static inline void RL_IX_with_LD_L(Z80* ctx, signed char d) { ctx->RL_IX_with_LD(d, 0b101); } + static inline void RL_IX_with_LD_A(Z80* ctx, signed char d) { ctx->RL_IX_with_LD(d, 0b111); } + inline void RL_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2415,18 +2202,18 @@ class Z80 } else { buf[0] = '\0'; } - return RL_IX(d, rp, buf); + RL_IX(d, rp, buf); } // Rotate Left memory with load Reg. - static inline int RL_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->RL_IY_with_LD(d, 0b000); } - static inline int RL_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->RL_IY_with_LD(d, 0b001); } - static inline int RL_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->RL_IY_with_LD(d, 0b010); } - static inline int RL_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->RL_IY_with_LD(d, 0b011); } - static inline int RL_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->RL_IY_with_LD(d, 0b100); } - static inline int RL_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->RL_IY_with_LD(d, 0b101); } - static inline int RL_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->RL_IY_with_LD(d, 0b111); } - inline int RL_IY_with_LD(signed char d, unsigned char r) + static inline void RL_IY_with_LD_B(Z80* ctx, signed char d) { ctx->RL_IY_with_LD(d, 0b000); } + static inline void RL_IY_with_LD_C(Z80* ctx, signed char d) { ctx->RL_IY_with_LD(d, 0b001); } + static inline void RL_IY_with_LD_D(Z80* ctx, signed char d) { ctx->RL_IY_with_LD(d, 0b010); } + static inline void RL_IY_with_LD_E(Z80* ctx, signed char d) { ctx->RL_IY_with_LD(d, 0b011); } + static inline void RL_IY_with_LD_H(Z80* ctx, signed char d) { ctx->RL_IY_with_LD(d, 0b100); } + static inline void RL_IY_with_LD_L(Z80* ctx, signed char d) { ctx->RL_IY_with_LD(d, 0b101); } + static inline void RL_IY_with_LD_A(Z80* ctx, signed char d) { ctx->RL_IY_with_LD(d, 0b111); } + inline void RL_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2435,32 +2222,30 @@ class Z80 } else { buf[0] = '\0'; } - return RL_IY(d, rp, buf); + RL_IY(d, rp, buf); } // Rotate Right memory - static inline int RR_IX_(Z80* ctx, signed char d) { return ctx->RR_IX(d); } - inline int RR_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RR_IX_(Z80* ctx, signed char d) { ctx->RR_IX(d); } + inline void RR_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RR (IX+d<$%04X>) = $%02X %s", reg.PC, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RR (IX+d<$%04X>) = $%02X %s", reg.PC - 4, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); unsigned char result = RR(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Rotate Right memory with load Reg. - static inline int RR_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->RR_IX_with_LD(d, 0b000); } - static inline int RR_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->RR_IX_with_LD(d, 0b001); } - static inline int RR_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->RR_IX_with_LD(d, 0b010); } - static inline int RR_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->RR_IX_with_LD(d, 0b011); } - static inline int RR_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->RR_IX_with_LD(d, 0b100); } - static inline int RR_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->RR_IX_with_LD(d, 0b101); } - static inline int RR_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->RR_IX_with_LD(d, 0b111); } - inline int RR_IX_with_LD(signed char d, unsigned char r) + static inline void RR_IX_with_LD_B(Z80* ctx, signed char d) { ctx->RR_IX_with_LD(d, 0b000); } + static inline void RR_IX_with_LD_C(Z80* ctx, signed char d) { ctx->RR_IX_with_LD(d, 0b001); } + static inline void RR_IX_with_LD_D(Z80* ctx, signed char d) { ctx->RR_IX_with_LD(d, 0b010); } + static inline void RR_IX_with_LD_E(Z80* ctx, signed char d) { ctx->RR_IX_with_LD(d, 0b011); } + static inline void RR_IX_with_LD_H(Z80* ctx, signed char d) { ctx->RR_IX_with_LD(d, 0b100); } + static inline void RR_IX_with_LD_L(Z80* ctx, signed char d) { ctx->RR_IX_with_LD(d, 0b101); } + static inline void RR_IX_with_LD_A(Z80* ctx, signed char d) { ctx->RR_IX_with_LD(d, 0b111); } + inline void RR_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2469,18 +2254,18 @@ class Z80 } else { buf[0] = '\0'; } - return RR_IX(d, rp, buf); + RR_IX(d, rp, buf); } // Rotate Right memory with load Reg. - static inline int RR_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->RR_IY_with_LD(d, 0b000); } - static inline int RR_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->RR_IY_with_LD(d, 0b001); } - static inline int RR_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->RR_IY_with_LD(d, 0b010); } - static inline int RR_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->RR_IY_with_LD(d, 0b011); } - static inline int RR_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->RR_IY_with_LD(d, 0b100); } - static inline int RR_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->RR_IY_with_LD(d, 0b101); } - static inline int RR_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->RR_IY_with_LD(d, 0b111); } - inline int RR_IY_with_LD(signed char d, unsigned char r) + static inline void RR_IY_with_LD_B(Z80* ctx, signed char d) { ctx->RR_IY_with_LD(d, 0b000); } + static inline void RR_IY_with_LD_C(Z80* ctx, signed char d) { ctx->RR_IY_with_LD(d, 0b001); } + static inline void RR_IY_with_LD_D(Z80* ctx, signed char d) { ctx->RR_IY_with_LD(d, 0b010); } + static inline void RR_IY_with_LD_E(Z80* ctx, signed char d) { ctx->RR_IY_with_LD(d, 0b011); } + static inline void RR_IY_with_LD_H(Z80* ctx, signed char d) { ctx->RR_IY_with_LD(d, 0b100); } + static inline void RR_IY_with_LD_L(Z80* ctx, signed char d) { ctx->RR_IY_with_LD(d, 0b101); } + static inline void RR_IY_with_LD_A(Z80* ctx, signed char d) { ctx->RR_IY_with_LD(d, 0b111); } + inline void RR_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2489,32 +2274,30 @@ class Z80 } else { buf[0] = '\0'; } - return RR_IY(d, rp, buf); + RR_IY(d, rp, buf); } // Shift operand location (IX+d) left Arithmetic - static inline int SLA_IX_(Z80* ctx, signed char d) { return ctx->SLA_IX(d); } - inline int SLA_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SLA_IX_(Z80* ctx, signed char d) { ctx->SLA_IX(d); } + inline void SLA_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SLA (IX+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SLA (IX+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SLA(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Shift operand location (IX+d) left Arithmetic with load Reg. - static inline int SLA_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->SLA_IX_with_LD(d, 0b000); } - static inline int SLA_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->SLA_IX_with_LD(d, 0b001); } - static inline int SLA_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->SLA_IX_with_LD(d, 0b010); } - static inline int SLA_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->SLA_IX_with_LD(d, 0b011); } - static inline int SLA_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->SLA_IX_with_LD(d, 0b100); } - static inline int SLA_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->SLA_IX_with_LD(d, 0b101); } - static inline int SLA_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->SLA_IX_with_LD(d, 0b111); } - inline int SLA_IX_with_LD(signed char d, unsigned char r) + static inline void SLA_IX_with_LD_B(Z80* ctx, signed char d) { ctx->SLA_IX_with_LD(d, 0b000); } + static inline void SLA_IX_with_LD_C(Z80* ctx, signed char d) { ctx->SLA_IX_with_LD(d, 0b001); } + static inline void SLA_IX_with_LD_D(Z80* ctx, signed char d) { ctx->SLA_IX_with_LD(d, 0b010); } + static inline void SLA_IX_with_LD_E(Z80* ctx, signed char d) { ctx->SLA_IX_with_LD(d, 0b011); } + static inline void SLA_IX_with_LD_H(Z80* ctx, signed char d) { ctx->SLA_IX_with_LD(d, 0b100); } + static inline void SLA_IX_with_LD_L(Z80* ctx, signed char d) { ctx->SLA_IX_with_LD(d, 0b101); } + static inline void SLA_IX_with_LD_A(Z80* ctx, signed char d) { ctx->SLA_IX_with_LD(d, 0b111); } + inline void SLA_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2523,18 +2306,18 @@ class Z80 } else { buf[0] = '\0'; } - return SLA_IX(d, rp, buf); + SLA_IX(d, rp, buf); } // Shift operand location (IY+d) left Arithmetic with load Reg. - static inline int SLA_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->SLA_IY_with_LD(d, 0b000); } - static inline int SLA_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->SLA_IY_with_LD(d, 0b001); } - static inline int SLA_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->SLA_IY_with_LD(d, 0b010); } - static inline int SLA_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->SLA_IY_with_LD(d, 0b011); } - static inline int SLA_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->SLA_IY_with_LD(d, 0b100); } - static inline int SLA_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->SLA_IY_with_LD(d, 0b101); } - static inline int SLA_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->SLA_IY_with_LD(d, 0b111); } - inline int SLA_IY_with_LD(signed char d, unsigned char r) + static inline void SLA_IY_with_LD_B(Z80* ctx, signed char d) { ctx->SLA_IY_with_LD(d, 0b000); } + static inline void SLA_IY_with_LD_C(Z80* ctx, signed char d) { ctx->SLA_IY_with_LD(d, 0b001); } + static inline void SLA_IY_with_LD_D(Z80* ctx, signed char d) { ctx->SLA_IY_with_LD(d, 0b010); } + static inline void SLA_IY_with_LD_E(Z80* ctx, signed char d) { ctx->SLA_IY_with_LD(d, 0b011); } + static inline void SLA_IY_with_LD_H(Z80* ctx, signed char d) { ctx->SLA_IY_with_LD(d, 0b100); } + static inline void SLA_IY_with_LD_L(Z80* ctx, signed char d) { ctx->SLA_IY_with_LD(d, 0b101); } + static inline void SLA_IY_with_LD_A(Z80* ctx, signed char d) { ctx->SLA_IY_with_LD(d, 0b111); } + inline void SLA_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2543,32 +2326,30 @@ class Z80 } else { buf[0] = '\0'; } - return SLA_IY(d, rp, buf); + SLA_IY(d, rp, buf); } // Shift operand location (IX+d) Right Arithmetic - static inline int SRA_IX_(Z80* ctx, signed char d) { return ctx->SRA_IX(d); } - inline int SRA_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SRA_IX_(Z80* ctx, signed char d) { ctx->SRA_IX(d); } + inline void SRA_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SRA (IX+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SRA (IX+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SRA(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Shift operand location (IX+d) right Arithmetic with load Reg. - static inline int SRA_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->SRA_IX_with_LD(d, 0b000); } - static inline int SRA_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->SRA_IX_with_LD(d, 0b001); } - static inline int SRA_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->SRA_IX_with_LD(d, 0b010); } - static inline int SRA_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->SRA_IX_with_LD(d, 0b011); } - static inline int SRA_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->SRA_IX_with_LD(d, 0b100); } - static inline int SRA_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->SRA_IX_with_LD(d, 0b101); } - static inline int SRA_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->SRA_IX_with_LD(d, 0b111); } - inline int SRA_IX_with_LD(signed char d, unsigned char r) + static inline void SRA_IX_with_LD_B(Z80* ctx, signed char d) { ctx->SRA_IX_with_LD(d, 0b000); } + static inline void SRA_IX_with_LD_C(Z80* ctx, signed char d) { ctx->SRA_IX_with_LD(d, 0b001); } + static inline void SRA_IX_with_LD_D(Z80* ctx, signed char d) { ctx->SRA_IX_with_LD(d, 0b010); } + static inline void SRA_IX_with_LD_E(Z80* ctx, signed char d) { ctx->SRA_IX_with_LD(d, 0b011); } + static inline void SRA_IX_with_LD_H(Z80* ctx, signed char d) { ctx->SRA_IX_with_LD(d, 0b100); } + static inline void SRA_IX_with_LD_L(Z80* ctx, signed char d) { ctx->SRA_IX_with_LD(d, 0b101); } + static inline void SRA_IX_with_LD_A(Z80* ctx, signed char d) { ctx->SRA_IX_with_LD(d, 0b111); } + inline void SRA_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2577,18 +2358,18 @@ class Z80 } else { buf[0] = '\0'; } - return SRA_IX(d, rp, buf); + SRA_IX(d, rp, buf); } // Shift operand location (IY+d) right Arithmetic with load Reg. - static inline int SRA_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->SRA_IY_with_LD(d, 0b000); } - static inline int SRA_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->SRA_IY_with_LD(d, 0b001); } - static inline int SRA_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->SRA_IY_with_LD(d, 0b010); } - static inline int SRA_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->SRA_IY_with_LD(d, 0b011); } - static inline int SRA_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->SRA_IY_with_LD(d, 0b100); } - static inline int SRA_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->SRA_IY_with_LD(d, 0b101); } - static inline int SRA_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->SRA_IY_with_LD(d, 0b111); } - inline int SRA_IY_with_LD(signed char d, unsigned char r) + static inline void SRA_IY_with_LD_B(Z80* ctx, signed char d) { ctx->SRA_IY_with_LD(d, 0b000); } + static inline void SRA_IY_with_LD_C(Z80* ctx, signed char d) { ctx->SRA_IY_with_LD(d, 0b001); } + static inline void SRA_IY_with_LD_D(Z80* ctx, signed char d) { ctx->SRA_IY_with_LD(d, 0b010); } + static inline void SRA_IY_with_LD_E(Z80* ctx, signed char d) { ctx->SRA_IY_with_LD(d, 0b011); } + static inline void SRA_IY_with_LD_H(Z80* ctx, signed char d) { ctx->SRA_IY_with_LD(d, 0b100); } + static inline void SRA_IY_with_LD_L(Z80* ctx, signed char d) { ctx->SRA_IY_with_LD(d, 0b101); } + static inline void SRA_IY_with_LD_A(Z80* ctx, signed char d) { ctx->SRA_IY_with_LD(d, 0b111); } + inline void SRA_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2597,32 +2378,30 @@ class Z80 } else { buf[0] = '\0'; } - return SRA_IY(d, rp, buf); + SRA_IY(d, rp, buf); } // Shift operand location (IX+d) Right Logical - static inline int SRL_IX_(Z80* ctx, signed char d) { return ctx->SRL_IX(d); } - inline int SRL_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SRL_IX_(Z80* ctx, signed char d) { ctx->SRL_IX(d); } + inline void SRL_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SRL (IX+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SRL (IX+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SRL(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Shift operand location (IX+d) Right Logical with load Reg. - static inline int SRL_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->SRL_IX_with_LD(d, 0b000); } - static inline int SRL_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->SRL_IX_with_LD(d, 0b001); } - static inline int SRL_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->SRL_IX_with_LD(d, 0b010); } - static inline int SRL_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->SRL_IX_with_LD(d, 0b011); } - static inline int SRL_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->SRL_IX_with_LD(d, 0b100); } - static inline int SRL_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->SRL_IX_with_LD(d, 0b101); } - static inline int SRL_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->SRL_IX_with_LD(d, 0b111); } - inline int SRL_IX_with_LD(signed char d, unsigned char r) + static inline void SRL_IX_with_LD_B(Z80* ctx, signed char d) { ctx->SRL_IX_with_LD(d, 0b000); } + static inline void SRL_IX_with_LD_C(Z80* ctx, signed char d) { ctx->SRL_IX_with_LD(d, 0b001); } + static inline void SRL_IX_with_LD_D(Z80* ctx, signed char d) { ctx->SRL_IX_with_LD(d, 0b010); } + static inline void SRL_IX_with_LD_E(Z80* ctx, signed char d) { ctx->SRL_IX_with_LD(d, 0b011); } + static inline void SRL_IX_with_LD_H(Z80* ctx, signed char d) { ctx->SRL_IX_with_LD(d, 0b100); } + static inline void SRL_IX_with_LD_L(Z80* ctx, signed char d) { ctx->SRL_IX_with_LD(d, 0b101); } + static inline void SRL_IX_with_LD_A(Z80* ctx, signed char d) { ctx->SRL_IX_with_LD(d, 0b111); } + inline void SRL_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2631,18 +2410,18 @@ class Z80 } else { buf[0] = '\0'; } - return SRL_IX(d, rp, buf); + SRL_IX(d, rp, buf); } // Shift operand location (IY+d) Right Logical with load Reg. - static inline int SRL_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->SRL_IY_with_LD(d, 0b000); } - static inline int SRL_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->SRL_IY_with_LD(d, 0b001); } - static inline int SRL_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->SRL_IY_with_LD(d, 0b010); } - static inline int SRL_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->SRL_IY_with_LD(d, 0b011); } - static inline int SRL_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->SRL_IY_with_LD(d, 0b100); } - static inline int SRL_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->SRL_IY_with_LD(d, 0b101); } - static inline int SRL_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->SRL_IY_with_LD(d, 0b111); } - inline int SRL_IY_with_LD(signed char d, unsigned char r) + static inline void SRL_IY_with_LD_B(Z80* ctx, signed char d) { ctx->SRL_IY_with_LD(d, 0b000); } + static inline void SRL_IY_with_LD_C(Z80* ctx, signed char d) { ctx->SRL_IY_with_LD(d, 0b001); } + static inline void SRL_IY_with_LD_D(Z80* ctx, signed char d) { ctx->SRL_IY_with_LD(d, 0b010); } + static inline void SRL_IY_with_LD_E(Z80* ctx, signed char d) { ctx->SRL_IY_with_LD(d, 0b011); } + static inline void SRL_IY_with_LD_H(Z80* ctx, signed char d) { ctx->SRL_IY_with_LD(d, 0b100); } + static inline void SRL_IY_with_LD_L(Z80* ctx, signed char d) { ctx->SRL_IY_with_LD(d, 0b101); } + static inline void SRL_IY_with_LD_A(Z80* ctx, signed char d) { ctx->SRL_IY_with_LD(d, 0b111); } + inline void SRL_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2651,33 +2430,31 @@ class Z80 } else { buf[0] = '\0'; } - return SRL_IY(d, rp, buf); + SRL_IY(d, rp, buf); } // Shift operand location (IX+d) Left Logical // NOTE: this function is only for SLL_IX_with_LD - static inline int SLL_IX_(Z80* ctx, signed char d) { return ctx->SLL_IX(d); } - inline int SLL_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SLL_IX_(Z80* ctx, signed char d) { ctx->SLL_IX(d); } + inline void SLL_IX(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SLL (IX+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SLL (IX+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SLL(n); writeByte(addr, result, 3); if (rp) *rp = result; - reg.PC += 4; - return 0; } // Shift operand location (IX+d) Left Logical with load Reg. - static inline int SLL_IX_with_LD_B(Z80* ctx, signed char d) { return ctx->SLL_IX_with_LD(d, 0b000); } - static inline int SLL_IX_with_LD_C(Z80* ctx, signed char d) { return ctx->SLL_IX_with_LD(d, 0b001); } - static inline int SLL_IX_with_LD_D(Z80* ctx, signed char d) { return ctx->SLL_IX_with_LD(d, 0b010); } - static inline int SLL_IX_with_LD_E(Z80* ctx, signed char d) { return ctx->SLL_IX_with_LD(d, 0b011); } - static inline int SLL_IX_with_LD_H(Z80* ctx, signed char d) { return ctx->SLL_IX_with_LD(d, 0b100); } - static inline int SLL_IX_with_LD_L(Z80* ctx, signed char d) { return ctx->SLL_IX_with_LD(d, 0b101); } - static inline int SLL_IX_with_LD_A(Z80* ctx, signed char d) { return ctx->SLL_IX_with_LD(d, 0b111); } - inline int SLL_IX_with_LD(signed char d, unsigned char r) + static inline void SLL_IX_with_LD_B(Z80* ctx, signed char d) { ctx->SLL_IX_with_LD(d, 0b000); } + static inline void SLL_IX_with_LD_C(Z80* ctx, signed char d) { ctx->SLL_IX_with_LD(d, 0b001); } + static inline void SLL_IX_with_LD_D(Z80* ctx, signed char d) { ctx->SLL_IX_with_LD(d, 0b010); } + static inline void SLL_IX_with_LD_E(Z80* ctx, signed char d) { ctx->SLL_IX_with_LD(d, 0b011); } + static inline void SLL_IX_with_LD_H(Z80* ctx, signed char d) { ctx->SLL_IX_with_LD(d, 0b100); } + static inline void SLL_IX_with_LD_L(Z80* ctx, signed char d) { ctx->SLL_IX_with_LD(d, 0b101); } + static inline void SLL_IX_with_LD_A(Z80* ctx, signed char d) { ctx->SLL_IX_with_LD(d, 0b111); } + inline void SLL_IX_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2686,33 +2463,31 @@ class Z80 } else { buf[0] = '\0'; } - return SLL_IX(d, rp, buf); + SLL_IX(d, rp, buf); } // Shift operand location (IY+d) Left Logical // NOTE: this function is only for SLL_IY_with_LD - static inline int SLL_IY_(Z80* ctx, signed char d) { return ctx->SLL_IY(d); } - inline int SLL_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SLL_IY_(Z80* ctx, signed char d) { ctx->SLL_IY(d); } + inline void SLL_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SLL (IY+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SLL (IY+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SLL(n); writeByte(addr, result, 3); if (rp) *rp = result; - reg.PC += 4; - return 0; } // Shift operand location (IY+d) Left Logical with load Reg. - static inline int SLL_IY_with_LD_B(Z80* ctx, signed char d) { return ctx->SLL_IY_with_LD(d, 0b000); } - static inline int SLL_IY_with_LD_C(Z80* ctx, signed char d) { return ctx->SLL_IY_with_LD(d, 0b001); } - static inline int SLL_IY_with_LD_D(Z80* ctx, signed char d) { return ctx->SLL_IY_with_LD(d, 0b010); } - static inline int SLL_IY_with_LD_E(Z80* ctx, signed char d) { return ctx->SLL_IY_with_LD(d, 0b011); } - static inline int SLL_IY_with_LD_H(Z80* ctx, signed char d) { return ctx->SLL_IY_with_LD(d, 0b100); } - static inline int SLL_IY_with_LD_L(Z80* ctx, signed char d) { return ctx->SLL_IY_with_LD(d, 0b101); } - static inline int SLL_IY_with_LD_A(Z80* ctx, signed char d) { return ctx->SLL_IY_with_LD(d, 0b111); } - inline int SLL_IY_with_LD(signed char d, unsigned char r) + static inline void SLL_IY_with_LD_B(Z80* ctx, signed char d) { ctx->SLL_IY_with_LD(d, 0b000); } + static inline void SLL_IY_with_LD_C(Z80* ctx, signed char d) { ctx->SLL_IY_with_LD(d, 0b001); } + static inline void SLL_IY_with_LD_D(Z80* ctx, signed char d) { ctx->SLL_IY_with_LD(d, 0b010); } + static inline void SLL_IY_with_LD_E(Z80* ctx, signed char d) { ctx->SLL_IY_with_LD(d, 0b011); } + static inline void SLL_IY_with_LD_H(Z80* ctx, signed char d) { ctx->SLL_IY_with_LD(d, 0b100); } + static inline void SLL_IY_with_LD_L(Z80* ctx, signed char d) { ctx->SLL_IY_with_LD(d, 0b101); } + static inline void SLL_IY_with_LD_A(Z80* ctx, signed char d) { ctx->SLL_IY_with_LD(d, 0b111); } + inline void SLL_IY_with_LD(signed char d, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -2721,105 +2496,91 @@ class Z80 } else { buf[0] = '\0'; } - return SLL_IY(d, rp, buf); + SLL_IY(d, rp, buf); } // Rotate memory (IY+d) Left Circular - static inline int RLC_IY_(Z80* ctx, signed char d) { return ctx->RLC_IY(d); } - inline int RLC_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RLC_IY_(Z80* ctx, signed char d) { ctx->RLC_IY(d); } + inline void RLC_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RLC (IY+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RLC (IY+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = RLC(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Rotate memory (IY+d) Right Circular - static inline int RRC_IY_(Z80* ctx, signed char d) { return ctx->RRC_IY(d); } - inline int RRC_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RRC_IY_(Z80* ctx, signed char d) { ctx->RRC_IY(d); } + inline void RRC_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RRC (IY+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RRC (IY+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = RRC(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Rotate Left memory - static inline int RL_IY_(Z80* ctx, signed char d) { return ctx->RL_IY(d); } - inline int RL_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RL_IY_(Z80* ctx, signed char d) { ctx->RL_IY(d); } + inline void RL_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RL (IY+d<$%04X>) = $%02X %s", reg.PC, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RL (IY+d<$%04X>) = $%02X %s", reg.PC - 4, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); unsigned char result = RL(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Shift operand location (IY+d) left Arithmetic - static inline int SLA_IY_(Z80* ctx, signed char d) { return ctx->SLA_IY(d); } - inline int SLA_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SLA_IY_(Z80* ctx, signed char d) { ctx->SLA_IY(d); } + inline void SLA_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SLA (IY+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SLA (IY+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SLA(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Rotate Right memory - static inline int RR_IY_(Z80* ctx, signed char d) { return ctx->RR_IY(d); } - inline int RR_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void RR_IY_(Z80* ctx, signed char d) { ctx->RR_IY(d); } + inline void RR_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RR (IY+d<$%04X>) = $%02X %s", reg.PC, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RR (IY+d<$%04X>) = $%02X %s", reg.PC - 4, addr, n, isFlagC() ? "ON" : "OFF", extraLog ? extraLog : ""); unsigned char result = RR(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Shift operand location (IY+d) Right Arithmetic - static inline int SRA_IY_(Z80* ctx, signed char d) { return ctx->SRA_IY(d); } - inline int SRA_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SRA_IY_(Z80* ctx, signed char d) { ctx->SRA_IY(d); } + inline void SRA_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SRA (IY+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SRA (IY+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SRA(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } // Shift operand location (IY+d) Right Logical - static inline int SRL_IY_(Z80* ctx, signed char d) { return ctx->SRL_IY(d); } - inline int SRL_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) + static inline void SRL_IY_(Z80* ctx, signed char d) { ctx->SRL_IY(d); } + inline void SRL_IY(signed char d, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SRL (IY+d<$%04X>) = $%02X%s", reg.PC, addr, n, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SRL (IY+d<$%04X>) = $%02X%s", reg.PC - 4, addr, n, extraLog ? extraLog : ""); unsigned char result = SRL(n); if (rp) *rp = result; writeByte(addr, result, 3); - reg.PC += 4; - return 0; } inline void addition8(int addition, int carry) { arithmetic8(false, addition, carry, true, true); } @@ -2867,683 +2628,574 @@ class Z80 } // Add Reg. r to Acc. - static inline int ADD_B(Z80* ctx) { return ctx->ADD_R(0b000); } - static inline int ADD_C(Z80* ctx) { return ctx->ADD_R(0b001); } - static inline int ADD_D(Z80* ctx) { return ctx->ADD_R(0b010); } - static inline int ADD_E(Z80* ctx) { return ctx->ADD_R(0b011); } - static inline int ADD_H(Z80* ctx) { return ctx->ADD_R(0b100); } - static inline int ADD_L(Z80* ctx) { return ctx->ADD_R(0b101); } - static inline int ADD_A(Z80* ctx) { return ctx->ADD_R(0b111); } - static inline int ADD_B_2(Z80* ctx) { return ctx->ADD_R(0b000, 2); } - static inline int ADD_C_2(Z80* ctx) { return ctx->ADD_R(0b001, 2); } - static inline int ADD_D_2(Z80* ctx) { return ctx->ADD_R(0b010, 2); } - static inline int ADD_E_2(Z80* ctx) { return ctx->ADD_R(0b011, 2); } - static inline int ADD_A_2(Z80* ctx) { return ctx->ADD_R(0b111, 2); } - inline int ADD_R(unsigned char r, int pc = 1) - { - if (isDebug()) log("[%04X] ADD %s, %s", reg.PC, registerDump(0b111), registerDump(r)); + static inline void ADD_B(Z80* ctx) { ctx->ADD_R(0b000); } + static inline void ADD_C(Z80* ctx) { ctx->ADD_R(0b001); } + static inline void ADD_D(Z80* ctx) { ctx->ADD_R(0b010); } + static inline void ADD_E(Z80* ctx) { ctx->ADD_R(0b011); } + static inline void ADD_H(Z80* ctx) { ctx->ADD_R(0b100); } + static inline void ADD_L(Z80* ctx) { ctx->ADD_R(0b101); } + static inline void ADD_A(Z80* ctx) { ctx->ADD_R(0b111); } + static inline void ADD_B_2(Z80* ctx) { ctx->ADD_R(0b000, 2); } + static inline void ADD_C_2(Z80* ctx) { ctx->ADD_R(0b001, 2); } + static inline void ADD_D_2(Z80* ctx) { ctx->ADD_R(0b010, 2); } + static inline void ADD_E_2(Z80* ctx) { ctx->ADD_R(0b011, 2); } + static inline void ADD_A_2(Z80* ctx) { ctx->ADD_R(0b111, 2); } + inline void ADD_R(unsigned char r, int pc = 1) + { + if (isDebug()) log("[%04X] ADD %s, %s", reg.PC - pc, registerDump(0b111), registerDump(r)); unsigned char* rp = getRegisterPointer(r); addition8(*rp, 0); - reg.PC += pc; - return 0; } // Add IXH to Acc. - static inline int ADD_IXH_(Z80* ctx) { return ctx->ADD_IXH(); } - inline int ADD_IXH() + static inline void ADD_IXH_(Z80* ctx) { ctx->ADD_IXH(); } + inline void ADD_IXH() { - if (isDebug()) log("[%04X] ADD %s, IXH<$%02X>", reg.PC, registerDump(0b111), getIXH()); + if (isDebug()) log("[%04X] ADD %s, IXH<$%02X>", reg.PC - 2, registerDump(0b111), getIXH()); addition8(getIXH(), 0); - reg.PC += 2; - return 0; } // Add IXL to Acc. - static inline int ADD_IXL_(Z80* ctx) { return ctx->ADD_IXL(); } - inline int ADD_IXL() + static inline void ADD_IXL_(Z80* ctx) { ctx->ADD_IXL(); } + inline void ADD_IXL() { - if (isDebug()) log("[%04X] ADD %s, IXL<$%02X>", reg.PC, registerDump(0b111), getIXL()); + if (isDebug()) log("[%04X] ADD %s, IXL<$%02X>", reg.PC - 2, registerDump(0b111), getIXL()); addition8(getIXL(), 0); - reg.PC += 2; - return 0; } // Add IYH to Acc. - static inline int ADD_IYH_(Z80* ctx) { return ctx->ADD_IYH(); } - inline int ADD_IYH() + static inline void ADD_IYH_(Z80* ctx) { ctx->ADD_IYH(); } + inline void ADD_IYH() { - if (isDebug()) log("[%04X] ADD %s, IYH<$%02X>", reg.PC, registerDump(0b111), getIYH()); + if (isDebug()) log("[%04X] ADD %s, IYH<$%02X>", reg.PC - 2, registerDump(0b111), getIYH()); addition8(getIYH(), 0); - reg.PC += 2; - return 0; } // Add IYL to Acc. - static inline int ADD_IYL_(Z80* ctx) { return ctx->ADD_IYL(); } - inline int ADD_IYL() + static inline void ADD_IYL_(Z80* ctx) { ctx->ADD_IYL(); } + inline void ADD_IYL() { - if (isDebug()) log("[%04X] ADD %s, IYL<$%02X>", reg.PC, registerDump(0b111), getIYL()); + if (isDebug()) log("[%04X] ADD %s, IYL<$%02X>", reg.PC - 2, registerDump(0b111), getIYL()); addition8(getIYL(), 0); - reg.PC += 2; - return 0; } // Add value n to Acc. - static inline int ADD_N(Z80* ctx) + static inline void ADD_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] ADD %s, $%02X", ctx->reg.PC, ctx->registerDump(0b111), n); + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] ADD %s, $%02X", ctx->reg.PC - 2, ctx->registerDump(0b111), n); ctx->addition8(n, 0); - ctx->reg.PC += 2; - return 0; } // Add location (HL) to Acc. - static inline int ADD_HL(Z80* ctx) + static inline void ADD_HL(Z80* ctx) { unsigned short addr = ctx->getHL(); unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] ADD %s, (%s) = $%02X", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); + if (ctx->isDebug()) ctx->log("[%04X] ADD %s, (%s) = $%02X", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); ctx->addition8(n, 0); - ctx->reg.PC += 1; - return 0; } // Add location (IX+d) to Acc. - static inline int ADD_IX_(Z80* ctx) { return ctx->ADD_IX(); } - inline int ADD_IX() + static inline void ADD_IX_(Z80* ctx) { ctx->ADD_IX(); } + inline void ADD_IX() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] ADD %s, (IX+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, n); + if (isDebug()) log("[%04X] ADD %s, (IX+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), addr, n); addition8(n, 0); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Add location (IY+d) to Acc. - static inline int ADD_IY_(Z80* ctx) { return ctx->ADD_IY(); } - inline int ADD_IY() + static inline void ADD_IY_(Z80* ctx) { ctx->ADD_IY(); } + inline void ADD_IY() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] ADD %s, (IY+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, n); + if (isDebug()) log("[%04X] ADD %s, (IY+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), addr, n); addition8(n, 0); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Add Resister with carry - static inline int ADC_B(Z80* ctx) { return ctx->ADC_R(0b000); } - static inline int ADC_C(Z80* ctx) { return ctx->ADC_R(0b001); } - static inline int ADC_D(Z80* ctx) { return ctx->ADC_R(0b010); } - static inline int ADC_E(Z80* ctx) { return ctx->ADC_R(0b011); } - static inline int ADC_H(Z80* ctx) { return ctx->ADC_R(0b100); } - static inline int ADC_L(Z80* ctx) { return ctx->ADC_R(0b101); } - static inline int ADC_A(Z80* ctx) { return ctx->ADC_R(0b111); } - static inline int ADC_B_2(Z80* ctx) { return ctx->ADC_R(0b000, 2); } - static inline int ADC_C_2(Z80* ctx) { return ctx->ADC_R(0b001, 2); } - static inline int ADC_D_2(Z80* ctx) { return ctx->ADC_R(0b010, 2); } - static inline int ADC_E_2(Z80* ctx) { return ctx->ADC_R(0b011, 2); } - static inline int ADC_A_2(Z80* ctx) { return ctx->ADC_R(0b111, 2); } - inline int ADC_R(unsigned char r, int pc = 1) + static inline void ADC_B(Z80* ctx) { ctx->ADC_R(0b000); } + static inline void ADC_C(Z80* ctx) { ctx->ADC_R(0b001); } + static inline void ADC_D(Z80* ctx) { ctx->ADC_R(0b010); } + static inline void ADC_E(Z80* ctx) { ctx->ADC_R(0b011); } + static inline void ADC_H(Z80* ctx) { ctx->ADC_R(0b100); } + static inline void ADC_L(Z80* ctx) { ctx->ADC_R(0b101); } + static inline void ADC_A(Z80* ctx) { ctx->ADC_R(0b111); } + static inline void ADC_B_2(Z80* ctx) { ctx->ADC_R(0b000, 2); } + static inline void ADC_C_2(Z80* ctx) { ctx->ADC_R(0b001, 2); } + static inline void ADC_D_2(Z80* ctx) { ctx->ADC_R(0b010, 2); } + static inline void ADC_E_2(Z80* ctx) { ctx->ADC_R(0b011, 2); } + static inline void ADC_A_2(Z80* ctx) { ctx->ADC_R(0b111, 2); } + inline void ADC_R(unsigned char r, int pc = 1) { unsigned char* rp = getRegisterPointer(r); unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] ADC %s, %s ", reg.PC, registerDump(0b111), registerDump(r), c ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, %s ", reg.PC - pc, registerDump(0b111), registerDump(r), c ? "ON" : "OFF"); addition8(*rp, c); - reg.PC += pc; - return 0; } // Add IXH to Acc. - static inline int ADC_IXH_(Z80* ctx) { return ctx->ADC_IXH(); } - inline int ADC_IXH() + static inline void ADC_IXH_(Z80* ctx) { ctx->ADC_IXH(); } + inline void ADC_IXH() { unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] ADC %s, IXH<$%02X> ", reg.PC, registerDump(0b111), getIXH(), c ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, IXH<$%02X> ", reg.PC - 2, registerDump(0b111), getIXH(), c ? "ON" : "OFF"); addition8(getIXH(), c); - reg.PC += 2; - return 0; } // Add IXL to Acc. - static inline int ADC_IXL_(Z80* ctx) { return ctx->ADC_IXL(); } - inline int ADC_IXL() + static inline void ADC_IXL_(Z80* ctx) { ctx->ADC_IXL(); } + inline void ADC_IXL() { unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] ADC %s, IXL<$%02X> ", reg.PC, registerDump(0b111), getIXL(), c ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, IXL<$%02X> ", reg.PC - 2, registerDump(0b111), getIXL(), c ? "ON" : "OFF"); addition8(getIXL(), c); - reg.PC += 2; - return 0; } // Add IYH to Acc. - static inline int ADC_IYH_(Z80* ctx) { return ctx->ADC_IYH(); } - inline int ADC_IYH() + static inline void ADC_IYH_(Z80* ctx) { ctx->ADC_IYH(); } + inline void ADC_IYH() { unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] ADC %s, IYH<$%02X> ", reg.PC, registerDump(0b111), getIYH(), c ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, IYH<$%02X> ", reg.PC - 2, registerDump(0b111), getIYH(), c ? "ON" : "OFF"); addition8(getIYH(), c); - reg.PC += 2; - return 0; } // Add IYL to Acc. - static inline int ADC_IYL_(Z80* ctx) { return ctx->ADC_IYL(); } - inline int ADC_IYL() + static inline void ADC_IYL_(Z80* ctx) { ctx->ADC_IYL(); } + inline void ADC_IYL() { unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] ADC %s, IYL<$%02X> ", reg.PC, registerDump(0b111), getIYL(), c ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, IYL<$%02X> ", reg.PC - 2, registerDump(0b111), getIYL(), c ? "ON" : "OFF"); addition8(getIYL(), c); - reg.PC += 2; - return 0; } // Add immediate with carry - static inline int ADC_N(Z80* ctx) + static inline void ADC_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); + unsigned char n = ctx->fetch(3); unsigned char c = ctx->isFlagC() ? 1 : 0; - if (ctx->isDebug()) ctx->log("[%04X] ADC %s, $%02X ", ctx->reg.PC, ctx->registerDump(0b111), n, c ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] ADC %s, $%02X ", ctx->reg.PC - 2, ctx->registerDump(0b111), n, c ? "ON" : "OFF"); ctx->addition8(n, c); - ctx->reg.PC += 2; - return 0; } // Add memory with carry - static inline int ADC_HL(Z80* ctx) + static inline void ADC_HL(Z80* ctx) { unsigned short addr = ctx->getHL(); unsigned char n = ctx->readByte(addr, 3); unsigned char c = ctx->isFlagC() ? 1 : 0; - if (ctx->isDebug()) ctx->log("[%04X] ADC %s, (%s) = $%02X ", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n, c ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] ADC %s, (%s) = $%02X ", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n, c ? "ON" : "OFF"); ctx->addition8(n, c); - ctx->reg.PC += 1; - return 0; } // Add memory with carry - static inline int ADC_IX_(Z80* ctx) { return ctx->ADC_IX(); } - inline int ADC_IX() + static inline void ADC_IX_(Z80* ctx) { ctx->ADC_IX(); } + inline void ADC_IX() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] ADC %s, (IX+d<$%04X>) = $%02X ", reg.PC, registerDump(0b111), addr, n, c ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, (IX+d<$%04X>) = $%02X ", reg.PC - 3, registerDump(0b111), addr, n, c ? "ON" : "OFF"); addition8(n, c); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Add memory with carry - static inline int ADC_IY_(Z80* ctx) { return ctx->ADC_IY(); } - inline int ADC_IY() + static inline void ADC_IY_(Z80* ctx) { ctx->ADC_IY(); } + inline void ADC_IY() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] ADC %s, (IY+d<$%04X>) = $%02X ", reg.PC, registerDump(0b111), addr, n, c ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, (IY+d<$%04X>) = $%02X ", reg.PC - 3, registerDump(0b111), addr, n, c ? "ON" : "OFF"); addition8(n, c); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Increment Register - static inline int INC_B(Z80* ctx) { return ctx->INC_R(0b000); } - static inline int INC_C(Z80* ctx) { return ctx->INC_R(0b001); } - static inline int INC_D(Z80* ctx) { return ctx->INC_R(0b010); } - static inline int INC_E(Z80* ctx) { return ctx->INC_R(0b011); } - static inline int INC_H(Z80* ctx) { return ctx->INC_R(0b100); } - static inline int INC_L(Z80* ctx) { return ctx->INC_R(0b101); } - static inline int INC_A(Z80* ctx) { return ctx->INC_R(0b111); } - static inline int INC_B_2(Z80* ctx) { return ctx->INC_R(0b000, 2); } - static inline int INC_C_2(Z80* ctx) { return ctx->INC_R(0b001, 2); } - static inline int INC_D_2(Z80* ctx) { return ctx->INC_R(0b010, 2); } - static inline int INC_E_2(Z80* ctx) { return ctx->INC_R(0b011, 2); } - static inline int INC_H_2(Z80* ctx) { return ctx->INC_R(0b100, 2); } - static inline int INC_L_2(Z80* ctx) { return ctx->INC_R(0b101, 2); } - static inline int INC_A_2(Z80* ctx) { return ctx->INC_R(0b111, 2); } - inline int INC_R(unsigned char r, int pc = 1) + static inline void INC_B(Z80* ctx) { ctx->INC_R(0b000); } + static inline void INC_C(Z80* ctx) { ctx->INC_R(0b001); } + static inline void INC_D(Z80* ctx) { ctx->INC_R(0b010); } + static inline void INC_E(Z80* ctx) { ctx->INC_R(0b011); } + static inline void INC_H(Z80* ctx) { ctx->INC_R(0b100); } + static inline void INC_L(Z80* ctx) { ctx->INC_R(0b101); } + static inline void INC_A(Z80* ctx) { ctx->INC_R(0b111); } + static inline void INC_B_2(Z80* ctx) { ctx->INC_R(0b000, 2); } + static inline void INC_C_2(Z80* ctx) { ctx->INC_R(0b001, 2); } + static inline void INC_D_2(Z80* ctx) { ctx->INC_R(0b010, 2); } + static inline void INC_E_2(Z80* ctx) { ctx->INC_R(0b011, 2); } + static inline void INC_A_2(Z80* ctx) { ctx->INC_R(0b111, 2); } + inline void INC_R(unsigned char r, int pc = 1) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] INC %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] INC %s", reg.PC - pc, registerDump(r)); setFlagByIncrement(*rp); (*rp)++; - reg.PC += pc; - return 0; } // Increment location (HL) - static inline int INC_HL(Z80* ctx) + static inline void INC_HL(Z80* ctx) { unsigned short addr = ctx->getHL(); unsigned char n = ctx->readByte(addr); - if (ctx->isDebug()) ctx->log("[%04X] INC (%s) = $%02X", ctx->reg.PC, ctx->registerPairDump(0b10), n); + if (ctx->isDebug()) ctx->log("[%04X] INC (%s) = $%02X", ctx->reg.PC - 1, ctx->registerPairDump(0b10), n); ctx->setFlagByIncrement(n); ctx->writeByte(addr, n + 1, 3); - ctx->reg.PC += 1; - return 0; } // Increment location (IX+d) - static inline int INC_IX_(Z80* ctx) { return ctx->INC_IX(); } - inline int INC_IX() + static inline void INC_IX_(Z80* ctx) { ctx->INC_IX(); } + inline void INC_IX() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] INC (IX+d<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] INC (IX+d<$%04X>) = $%02X", reg.PC - 3, addr, n); setFlagByIncrement(n); writeByte(addr, n + 1); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Increment register high 8 bits of IX - static inline int INC_IXH_(Z80* ctx) { return ctx->INC_IXH(); } - inline int INC_IXH() + static inline void INC_IXH_(Z80* ctx) { ctx->INC_IXH(); } + inline void INC_IXH() { unsigned char ixh = getIXH(); - if (isDebug()) log("[%04X] INC IXH<$%02X>", reg.PC, ixh); + if (isDebug()) log("[%04X] INC IXH<$%02X>", reg.PC - 2, ixh); setFlagByIncrement(ixh++); setIXH(ixh); - reg.PC += 2; - return 0; } // Increment register low 8 bits of IX - static inline int INC_IXL_(Z80* ctx) { return ctx->INC_IXL(); } - inline int INC_IXL() + static inline void INC_IXL_(Z80* ctx) { ctx->INC_IXL(); } + inline void INC_IXL() { unsigned char ixl = getIXL(); - if (isDebug()) log("[%04X] INC IXL<$%02X>", reg.PC, ixl); + if (isDebug()) log("[%04X] INC IXL<$%02X>", reg.PC - 2, ixl); setFlagByIncrement(ixl++); setIXL(ixl); - reg.PC += 2; - return 0; } // Increment location (IY+d) - static inline int INC_IY_(Z80* ctx) { return ctx->INC_IY(); } - inline int INC_IY() + static inline void INC_IY_(Z80* ctx) { ctx->INC_IY(); } + inline void INC_IY() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] INC (IY+d<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] INC (IY+d<$%04X>) = $%02X", reg.PC - 3, addr, n); setFlagByIncrement(n); writeByte(addr, n + 1); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Increment register high 8 bits of IY - static inline int INC_IYH_(Z80* ctx) { return ctx->INC_IYH(); } - inline int INC_IYH() + static inline void INC_IYH_(Z80* ctx) { ctx->INC_IYH(); } + inline void INC_IYH() { unsigned char iyh = getIYH(); - if (isDebug()) log("[%04X] INC IYH<$%02X>", reg.PC, iyh); + if (isDebug()) log("[%04X] INC IYH<$%02X>", reg.PC - 2, iyh); setFlagByIncrement(iyh++); setIYH(iyh); - reg.PC += 2; - return 0; } // Increment register low 8 bits of IY - static inline int INC_IYL_(Z80* ctx) { return ctx->INC_IYL(); } - inline int INC_IYL() + static inline void INC_IYL_(Z80* ctx) { ctx->INC_IYL(); } + inline void INC_IYL() { unsigned char iyl = getIYL(); - if (isDebug()) log("[%04X] INC IYL<$%02X>", reg.PC, iyl); + if (isDebug()) log("[%04X] INC IYL<$%02X>", reg.PC - 2, iyl); setFlagByIncrement(iyl++); setIYL(iyl); - reg.PC += 2; - return 0; } // Subtract Register - static inline int SUB_B(Z80* ctx) { return ctx->SUB_R(0b000); } - static inline int SUB_C(Z80* ctx) { return ctx->SUB_R(0b001); } - static inline int SUB_D(Z80* ctx) { return ctx->SUB_R(0b010); } - static inline int SUB_E(Z80* ctx) { return ctx->SUB_R(0b011); } - static inline int SUB_H(Z80* ctx) { return ctx->SUB_R(0b100); } - static inline int SUB_L(Z80* ctx) { return ctx->SUB_R(0b101); } - static inline int SUB_A(Z80* ctx) { return ctx->SUB_R(0b111); } - static inline int SUB_B_2(Z80* ctx) { return ctx->SUB_R(0b000, 2); } - static inline int SUB_C_2(Z80* ctx) { return ctx->SUB_R(0b001, 2); } - static inline int SUB_D_2(Z80* ctx) { return ctx->SUB_R(0b010, 2); } - static inline int SUB_E_2(Z80* ctx) { return ctx->SUB_R(0b011, 2); } - static inline int SUB_A_2(Z80* ctx) { return ctx->SUB_R(0b111, 2); } - inline int SUB_R(unsigned char r, int pc = 1) - { - if (isDebug()) log("[%04X] SUB %s, %s", reg.PC, registerDump(0b111), registerDump(r)); + static inline void SUB_B(Z80* ctx) { ctx->SUB_R(0b000); } + static inline void SUB_C(Z80* ctx) { ctx->SUB_R(0b001); } + static inline void SUB_D(Z80* ctx) { ctx->SUB_R(0b010); } + static inline void SUB_E(Z80* ctx) { ctx->SUB_R(0b011); } + static inline void SUB_H(Z80* ctx) { ctx->SUB_R(0b100); } + static inline void SUB_L(Z80* ctx) { ctx->SUB_R(0b101); } + static inline void SUB_A(Z80* ctx) { ctx->SUB_R(0b111); } + static inline void SUB_B_2(Z80* ctx) { ctx->SUB_R(0b000, 2); } + static inline void SUB_C_2(Z80* ctx) { ctx->SUB_R(0b001, 2); } + static inline void SUB_D_2(Z80* ctx) { ctx->SUB_R(0b010, 2); } + static inline void SUB_E_2(Z80* ctx) { ctx->SUB_R(0b011, 2); } + static inline void SUB_A_2(Z80* ctx) { ctx->SUB_R(0b111, 2); } + inline void SUB_R(unsigned char r, int pc = 1) + { + if (isDebug()) log("[%04X] SUB %s, %s", reg.PC - pc, registerDump(0b111), registerDump(r)); unsigned char* rp = getRegisterPointer(r); subtract8(*rp, 0); - reg.PC += pc; - return 0; } // Subtract IXH to Acc. - static inline int SUB_IXH_(Z80* ctx) { return ctx->SUB_IXH(); } - inline int SUB_IXH() + static inline void SUB_IXH_(Z80* ctx) { ctx->SUB_IXH(); } + inline void SUB_IXH() { - if (isDebug()) log("[%04X] SUB %s, IXH<$%02X>", reg.PC, registerDump(0b111), getIXH()); + if (isDebug()) log("[%04X] SUB %s, IXH<$%02X>", reg.PC - 2, registerDump(0b111), getIXH()); subtract8(getIXH(), 0); - reg.PC += 2; - return 0; } // Subtract IXL to Acc. - static inline int SUB_IXL_(Z80* ctx) { return ctx->SUB_IXL(); } - inline int SUB_IXL() + static inline void SUB_IXL_(Z80* ctx) { ctx->SUB_IXL(); } + inline void SUB_IXL() { - if (isDebug()) log("[%04X] SUB %s, IXL<$%02X>", reg.PC, registerDump(0b111), getIXL()); + if (isDebug()) log("[%04X] SUB %s, IXL<$%02X>", reg.PC - 2, registerDump(0b111), getIXL()); subtract8(getIXL(), 0); - reg.PC += 2; - return 0; } // Subtract IYH to Acc. - static inline int SUB_IYH_(Z80* ctx) { return ctx->SUB_IYH(); } - inline int SUB_IYH() + static inline void SUB_IYH_(Z80* ctx) { ctx->SUB_IYH(); } + inline void SUB_IYH() { - if (isDebug()) log("[%04X] SUB %s, IYH<$%02X>", reg.PC, registerDump(0b111), getIYH()); + if (isDebug()) log("[%04X] SUB %s, IYH<$%02X>", reg.PC - 2, registerDump(0b111), getIYH()); subtract8(getIYH(), 0); - reg.PC += 2; - return 0; } // Subtract IYL to Acc. - static inline int SUB_IYL_(Z80* ctx) { return ctx->SUB_IYL(); } - inline int SUB_IYL() + static inline void SUB_IYL_(Z80* ctx) { ctx->SUB_IYL(); } + inline void SUB_IYL() { - if (isDebug()) log("[%04X] SUB %s, IYL<$%02X>", reg.PC, registerDump(0b111), getIYL()); + if (isDebug()) log("[%04X] SUB %s, IYL<$%02X>", reg.PC - 2, registerDump(0b111), getIYL()); subtract8(getIYL(), 0); - reg.PC += 2; - return 0; } // Subtract immediate - static inline int SUB_N(Z80* ctx) + static inline void SUB_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] SUB %s, $%02X", ctx->reg.PC, ctx->registerDump(0b111), n); + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] SUB %s, $%02X", ctx->reg.PC - 2, ctx->registerDump(0b111), n); ctx->subtract8(n, 0); - ctx->reg.PC += 2; - return 0; } // Subtract memory - static inline int SUB_HL(Z80* ctx) + static inline void SUB_HL(Z80* ctx) { unsigned short addr = ctx->getHL(); unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] SUB %s, (%s) = $%02X", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); + if (ctx->isDebug()) ctx->log("[%04X] SUB %s, (%s) = $%02X", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); ctx->subtract8(n, 0); - ctx->reg.PC += 1; - return 0; } // Subtract memory - static inline int SUB_IX_(Z80* ctx) { return ctx->SUB_IX(); } - inline int SUB_IX() + static inline void SUB_IX_(Z80* ctx) { ctx->SUB_IX(); } + inline void SUB_IX() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SUB %s, (IX+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, n); + if (isDebug()) log("[%04X] SUB %s, (IX+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), addr, n); subtract8(n, 0); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Subtract memory - static inline int SUB_IY_(Z80* ctx) { return ctx->SUB_IY(); } - inline int SUB_IY() + static inline void SUB_IY_(Z80* ctx) { ctx->SUB_IY(); } + inline void SUB_IY() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SUB %s, (IY+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, n); + if (isDebug()) log("[%04X] SUB %s, (IY+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), addr, n); subtract8(n, 0); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Subtract Resister with carry - static inline int SBC_B(Z80* ctx) { return ctx->SBC_R(0b000); } - static inline int SBC_C(Z80* ctx) { return ctx->SBC_R(0b001); } - static inline int SBC_D(Z80* ctx) { return ctx->SBC_R(0b010); } - static inline int SBC_E(Z80* ctx) { return ctx->SBC_R(0b011); } - static inline int SBC_H(Z80* ctx) { return ctx->SBC_R(0b100); } - static inline int SBC_L(Z80* ctx) { return ctx->SBC_R(0b101); } - static inline int SBC_A(Z80* ctx) { return ctx->SBC_R(0b111); } - static inline int SBC_B_2(Z80* ctx) { return ctx->SBC_R(0b000, 2); } - static inline int SBC_C_2(Z80* ctx) { return ctx->SBC_R(0b001, 2); } - static inline int SBC_D_2(Z80* ctx) { return ctx->SBC_R(0b010, 2); } - static inline int SBC_E_2(Z80* ctx) { return ctx->SBC_R(0b011, 2); } - static inline int SBC_A_2(Z80* ctx) { return ctx->SBC_R(0b111, 2); } - inline int SBC_R(unsigned char r, int pc = 1) - { - unsigned char* rp = getRegisterPointer(r); - unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] SBC %s, %s ", reg.PC, registerDump(0b111), registerDump(r), c ? "ON" : "OFF"); - subtract8(*rp, c); - reg.PC += pc; - return 0; + static inline void SBC_B(Z80* ctx) { ctx->SBC_R(0b000); } + static inline void SBC_C(Z80* ctx) { ctx->SBC_R(0b001); } + static inline void SBC_D(Z80* ctx) { ctx->SBC_R(0b010); } + static inline void SBC_E(Z80* ctx) { ctx->SBC_R(0b011); } + static inline void SBC_H(Z80* ctx) { ctx->SBC_R(0b100); } + static inline void SBC_L(Z80* ctx) { ctx->SBC_R(0b101); } + static inline void SBC_A(Z80* ctx) { ctx->SBC_R(0b111); } + static inline void SBC_B_2(Z80* ctx) { ctx->SBC_R(0b000, 2); } + static inline void SBC_C_2(Z80* ctx) { ctx->SBC_R(0b001, 2); } + static inline void SBC_D_2(Z80* ctx) { ctx->SBC_R(0b010, 2); } + static inline void SBC_E_2(Z80* ctx) { ctx->SBC_R(0b011, 2); } + static inline void SBC_A_2(Z80* ctx) { ctx->SBC_R(0b111, 2); } + inline void SBC_R(unsigned char r, int pc = 1) + { + if (isDebug()) log("[%04X] SBC %s, %s ", reg.PC - pc, registerDump(0b111), registerDump(r), isFlagC() ? "ON" : "OFF"); + subtract8(getRegister(r), isFlagC() ? 1 : 0); } // Subtract IXH to Acc. with carry - static inline int SBC_IXH_(Z80* ctx) { return ctx->SBC_IXH(); } - inline int SBC_IXH() + static inline void SBC_IXH_(Z80* ctx) { ctx->SBC_IXH(); } + inline void SBC_IXH() { - unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] SBC %s, IXH<$%02X> ", reg.PC, registerDump(0b111), getIXH(), c ? "ON" : "OFF"); - subtract8(getIXH(), c); - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] SBC %s, IXH<$%02X> ", reg.PC - 2, registerDump(0b111), getIXH(), isFlagC() ? "ON" : "OFF"); + subtract8(getIXH(), isFlagC() ? 1 : 0); } // Subtract IXL to Acc. with carry - static inline int SBC_IXL_(Z80* ctx) { return ctx->SBC_IXL(); } - inline int SBC_IXL() + static inline void SBC_IXL_(Z80* ctx) { ctx->SBC_IXL(); } + inline void SBC_IXL() { - unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] SBC %s, IXL<$%02X> ", reg.PC, registerDump(0b111), getIXL(), c ? "ON" : "OFF"); - subtract8(getIXL(), c); - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] SBC %s, IXL<$%02X> ", reg.PC - 2, registerDump(0b111), getIXL(), isFlagC() ? "ON" : "OFF"); + subtract8(getIXL(), isFlagC() ? 1 : 0); } // Subtract IYH to Acc. with carry - static inline int SBC_IYH_(Z80* ctx) { return ctx->SBC_IYH(); } - inline int SBC_IYH() + static inline void SBC_IYH_(Z80* ctx) { ctx->SBC_IYH(); } + inline void SBC_IYH() { - unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] SBC %s, IYH<$%02X> ", reg.PC, registerDump(0b111), getIYH(), c ? "ON" : "OFF"); - subtract8(getIYH(), c); - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] SBC %s, IYH<$%02X> ", reg.PC - 2, registerDump(0b111), getIYH(), isFlagC() ? "ON" : "OFF"); + subtract8(getIYH(), isFlagC() ? 1 : 0); } // Subtract IYL to Acc. with carry - static inline int SBC_IYL_(Z80* ctx) { return ctx->SBC_IYL(); } - inline int SBC_IYL() + static inline void SBC_IYL_(Z80* ctx) { ctx->SBC_IYL(); } + inline void SBC_IYL() { - unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] SBC %s, IYL<$%02X> ", reg.PC, registerDump(0b111), getIYL(), c ? "ON" : "OFF"); - subtract8(getIYL(), c); - reg.PC += 2; - return 0; + if (isDebug()) log("[%04X] SBC %s, IYL<$%02X> ", reg.PC - 2, registerDump(0b111), getIYL(), isFlagC() ? "ON" : "OFF"); + subtract8(getIYL(), isFlagC() ? 1 : 0); } // Subtract immediate with carry - static inline int SBC_N(Z80* ctx) + static inline void SBC_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - unsigned char c = ctx->isFlagC() ? 1 : 0; - if (ctx->isDebug()) ctx->log("[%04X] SBC %s, $%02X ", ctx->reg.PC, ctx->registerDump(0b111), n, c ? "ON" : "OFF"); - ctx->subtract8(n, c); - ctx->reg.PC += 2; - return 0; + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] SBC %s, $%02X ", ctx->reg.PC - 2, ctx->registerDump(0b111), n, ctx->isFlagC() ? "ON" : "OFF"); + ctx->subtract8(n, ctx->isFlagC() ? 1 : 0); } // Subtract memory with carry - static inline int SBC_HL(Z80* ctx) + static inline void SBC_HL(Z80* ctx) { - unsigned short addr = ctx->getHL(); - unsigned char n = ctx->readByte(addr, 3); - unsigned char c = ctx->isFlagC() ? 1 : 0; - if (ctx->isDebug()) ctx->log("[%04X] SBC %s, (%s) = $%02X ", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n, c ? "ON" : "OFF"); - ctx->subtract8(n, c); - ctx->reg.PC += 1; - return 0; + unsigned char n = ctx->readByte(ctx->getHL(), 3); + if (ctx->isDebug()) ctx->log("[%04X] SBC %s, (%s) = $%02X ", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n, ctx->isFlagC() ? "ON" : "OFF"); + ctx->subtract8(n, ctx->isFlagC() ? 1 : 0); } // Subtract memory with carry - static inline int SBC_IX_(Z80* ctx) { return ctx->SBC_IX(); } - inline int SBC_IX() + static inline void SBC_IX_(Z80* ctx) { ctx->SBC_IX(); } + inline void SBC_IX() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IX + d); - unsigned char n = readByte(addr); - unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] SBC %s, (IX+d<$%04X>) = $%02X ", reg.PC, registerDump(0b111), addr, n, c ? "ON" : "OFF"); - subtract8(n, c); - reg.PC += 3; - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IX + d)); + if (isDebug()) log("[%04X] SBC %s, (IX+d<$%04X>) = $%02X ", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IX + d), n, isFlagC() ? "ON" : "OFF"); + subtract8(n, isFlagC() ? 1 : 0); + consumeClock(3); } // Subtract memory with carry - static inline int SBC_IY_(Z80* ctx) { return ctx->SBC_IY(); } - inline int SBC_IY() + static inline void SBC_IY_(Z80* ctx) { ctx->SBC_IY(); } + inline void SBC_IY() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IY + d); - unsigned char n = readByte(addr); - unsigned char c = isFlagC() ? 1 : 0; - if (isDebug()) log("[%04X] SBC %s, (IY+d<$%04X>) = $%02X ", reg.PC, registerDump(0b111), addr, n, c ? "ON" : "OFF"); - subtract8(n, c); - reg.PC += 3; - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IY + d)); + if (isDebug()) log("[%04X] SBC %s, (IY+d<$%04X>) = $%02X ", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IY + d), n, isFlagC() ? "ON" : "OFF"); + subtract8(n, isFlagC() ? 1 : 0); + consumeClock(3); } // Decrement Register - static inline int DEC_B(Z80* ctx) { return ctx->DEC_R(0b000); } - static inline int DEC_C(Z80* ctx) { return ctx->DEC_R(0b001); } - static inline int DEC_D(Z80* ctx) { return ctx->DEC_R(0b010); } - static inline int DEC_E(Z80* ctx) { return ctx->DEC_R(0b011); } - static inline int DEC_H(Z80* ctx) { return ctx->DEC_R(0b100); } - static inline int DEC_L(Z80* ctx) { return ctx->DEC_R(0b101); } - static inline int DEC_A(Z80* ctx) { return ctx->DEC_R(0b111); } - static inline int DEC_B_2(Z80* ctx) { return ctx->DEC_R(0b000, 2); } - static inline int DEC_C_2(Z80* ctx) { return ctx->DEC_R(0b001, 2); } - static inline int DEC_D_2(Z80* ctx) { return ctx->DEC_R(0b010, 2); } - static inline int DEC_E_2(Z80* ctx) { return ctx->DEC_R(0b011, 2); } - static inline int DEC_H_2(Z80* ctx) { return ctx->DEC_R(0b100, 2); } - static inline int DEC_L_2(Z80* ctx) { return ctx->DEC_R(0b101, 2); } - static inline int DEC_A_2(Z80* ctx) { return ctx->DEC_R(0b111, 2); } - inline int DEC_R(unsigned char r, int pc = 1) + static inline void DEC_B(Z80* ctx) { ctx->DEC_R(0b000); } + static inline void DEC_C(Z80* ctx) { ctx->DEC_R(0b001); } + static inline void DEC_D(Z80* ctx) { ctx->DEC_R(0b010); } + static inline void DEC_E(Z80* ctx) { ctx->DEC_R(0b011); } + static inline void DEC_H(Z80* ctx) { ctx->DEC_R(0b100); } + static inline void DEC_L(Z80* ctx) { ctx->DEC_R(0b101); } + static inline void DEC_A(Z80* ctx) { ctx->DEC_R(0b111); } + static inline void DEC_B_2(Z80* ctx) { ctx->DEC_R(0b000, 2); } + static inline void DEC_C_2(Z80* ctx) { ctx->DEC_R(0b001, 2); } + static inline void DEC_D_2(Z80* ctx) { ctx->DEC_R(0b010, 2); } + static inline void DEC_E_2(Z80* ctx) { ctx->DEC_R(0b011, 2); } + static inline void DEC_A_2(Z80* ctx) { ctx->DEC_R(0b111, 2); } + inline void DEC_R(unsigned char r, int pc = 1) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] DEC %s", reg.PC, registerDump(r)); + if (isDebug()) log("[%04X] DEC %s", reg.PC - pc, registerDump(r)); setFlagByDecrement(*rp); (*rp)--; - reg.PC += pc; - return 0; } // Decrement location (HL) - static inline int DEC_HL(Z80* ctx) + static inline void DEC_HL(Z80* ctx) { unsigned short addr = ctx->getHL(); unsigned char n = ctx->readByte(addr); - if (ctx->isDebug()) ctx->log("[%04X] DEC (%s) = $%02X", ctx->reg.PC, ctx->registerPairDump(0b10), n); + if (ctx->isDebug()) ctx->log("[%04X] DEC (%s) = $%02X", ctx->reg.PC - 1, ctx->registerPairDump(0b10), n); ctx->setFlagByDecrement(n); ctx->writeByte(addr, n - 1, 3); - ctx->reg.PC += 1; - return 0; } // Decrement location (IX+d) - static inline int DEC_IX_(Z80* ctx) { return ctx->DEC_IX(); } - inline int DEC_IX() + static inline void DEC_IX_(Z80* ctx) { ctx->DEC_IX(); } + inline void DEC_IX() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] DEC (IX+d<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] DEC (IX+d<$%04X>) = $%02X", reg.PC - 3, addr, n); setFlagByDecrement(n); writeByte(addr, n - 1); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Decrement high 8 bits of IX - static inline int DEC_IXH_(Z80* ctx) { return ctx->DEC_IXH(); } - inline int DEC_IXH() + static inline void DEC_IXH_(Z80* ctx) { ctx->DEC_IXH(); } + inline void DEC_IXH() { unsigned char ixh = getIXH(); - if (isDebug()) log("[%04X] DEC IXH<$%02X>", reg.PC, ixh); + if (isDebug()) log("[%04X] DEC IXH<$%02X>", reg.PC - 2, ixh); setFlagByDecrement(ixh--); setIXH(ixh); - reg.PC += 2; - return 0; } // Decrement low 8 bits of IX - static inline int DEC_IXL_(Z80* ctx) { return ctx->DEC_IXL(); } - inline int DEC_IXL() + static inline void DEC_IXL_(Z80* ctx) { ctx->DEC_IXL(); } + inline void DEC_IXL() { unsigned char ixl = getIXL(); - if (isDebug()) log("[%04X] DEC IXL<$%02X>", reg.PC, ixl); + if (isDebug()) log("[%04X] DEC IXL<$%02X>", reg.PC - 2, ixl); setFlagByDecrement(ixl--); setIXL(ixl); - reg.PC += 2; - return 0; } // Decrement location (IY+d) - static inline int DEC_IY_(Z80* ctx) { return ctx->DEC_IY(); } - inline int DEC_IY() + static inline void DEC_IY_(Z80* ctx) { ctx->DEC_IY(); } + inline void DEC_IY() { - signed char d = (signed char)readByte(reg.PC + 2); + signed char d = (signed char)fetch(4); unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] DEC (IY+d<$%04X>) = $%02X", reg.PC, addr, n); + if (isDebug()) log("[%04X] DEC (IY+d<$%04X>) = $%02X", reg.PC - 3, addr, n); setFlagByDecrement(n); writeByte(addr, n - 1); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Decrement high 8 bits of IY - static inline int DEC_IYH_(Z80* ctx) { return ctx->DEC_IYH(); } - inline int DEC_IYH() + static inline void DEC_IYH_(Z80* ctx) { ctx->DEC_IYH(); } + inline void DEC_IYH() { unsigned char iyh = getIYH(); - if (isDebug()) log("[%04X] DEC IYH<$%02X>", reg.PC, iyh); + if (isDebug()) log("[%04X] DEC IYH<$%02X>", reg.PC - 2, iyh); setFlagByDecrement(iyh--); setIYH(iyh); - reg.PC += 2; - return 0; } // Decrement low 8 bits of IY - static inline int DEC_IYL_(Z80* ctx) { return ctx->DEC_IYL(); } - inline int DEC_IYL() + static inline void DEC_IYL_(Z80* ctx) { ctx->DEC_IYL(); } + inline void DEC_IYL() { unsigned char iyl = getIYL(); - if (isDebug()) log("[%04X] DEC IYL<$%02X>", reg.PC, iyl); + if (isDebug()) log("[%04X] DEC IYL<$%02X>", reg.PC - 2, iyl); setFlagByDecrement(iyl--); setIYL(iyl); - reg.PC += 2; - return 0; } inline void setFlagByAdd16(unsigned short before, unsigned short addition) @@ -3573,136 +3225,124 @@ class Z80 } // Add register pair to H and L - static inline int ADD_HL_BC(Z80* ctx) { return ctx->ADD_HL_RP(0b00); } - static inline int ADD_HL_DE(Z80* ctx) { return ctx->ADD_HL_RP(0b01); } - static inline int ADD_HL_HL(Z80* ctx) { return ctx->ADD_HL_RP(0b10); } - static inline int ADD_HL_SP(Z80* ctx) { return ctx->ADD_HL_RP(0b11); } - inline int ADD_HL_RP(unsigned char rp) + static inline void ADD_HL_BC(Z80* ctx) { ctx->ADD_HL_RP(0b00); } + static inline void ADD_HL_DE(Z80* ctx) { ctx->ADD_HL_RP(0b01); } + static inline void ADD_HL_HL(Z80* ctx) { ctx->ADD_HL_RP(0b10); } + static inline void ADD_HL_SP(Z80* ctx) { ctx->ADD_HL_RP(0b11); } + inline void ADD_HL_RP(unsigned char rp) { - if (isDebug()) log("[%04X] ADD %s, %s", reg.PC, registerPairDump(0b10), registerPairDump(rp)); + if (isDebug()) log("[%04X] ADD %s, %s", reg.PC - 1, registerPairDump(0b10), registerPairDump(rp)); unsigned short hl = getHL(); unsigned short nn = getRP(rp); reg.WZ = nn + 1; setFlagByAdd16(hl, nn); setHL(hl + nn); - reg.PC++; - return consumeClock(7); + consumeClock(7); } // Add with carry register pair to HL - static inline int ADC_HL_BC(Z80* ctx) { return ctx->ADC_HL_RP(0b00); } - static inline int ADC_HL_DE(Z80* ctx) { return ctx->ADC_HL_RP(0b01); } - static inline int ADC_HL_HL(Z80* ctx) { return ctx->ADC_HL_RP(0b10); } - static inline int ADC_HL_SP(Z80* ctx) { return ctx->ADC_HL_RP(0b11); } - inline int ADC_HL_RP(unsigned char rp) + static inline void ADC_HL_BC(Z80* ctx) { ctx->ADC_HL_RP(0b00); } + static inline void ADC_HL_DE(Z80* ctx) { ctx->ADC_HL_RP(0b01); } + static inline void ADC_HL_HL(Z80* ctx) { ctx->ADC_HL_RP(0b10); } + static inline void ADC_HL_SP(Z80* ctx) { ctx->ADC_HL_RP(0b11); } + inline void ADC_HL_RP(unsigned char rp) { - if (isDebug()) log("[%04X] ADC %s, %s ", reg.PC, registerPairDump(0b10), registerPairDump(rp), isFlagC() ? "ON" : "OFF"); + if (isDebug()) log("[%04X] ADC %s, %s ", reg.PC - 2, registerPairDump(0b10), registerPairDump(rp), isFlagC() ? "ON" : "OFF"); unsigned short hl = getHL(); unsigned short nn = getRP(rp); unsigned char c = isFlagC() ? 1 : 0; reg.WZ = hl + 1; setFlagByAdc16(hl, c + nn); setHL(hl + c + nn); - reg.PC += 2; - return consumeClock(7); + consumeClock(7); } // Add register pair to IX - static inline int ADD_IX_BC(Z80* ctx) { return ctx->ADD_IX_RP(0b00); } - static inline int ADD_IX_DE(Z80* ctx) { return ctx->ADD_IX_RP(0b01); } - static inline int ADD_IX_IX(Z80* ctx) { return ctx->ADD_IX_RP(0b10); } - static inline int ADD_IX_SP(Z80* ctx) { return ctx->ADD_IX_RP(0b11); } - inline int ADD_IX_RP(unsigned char rp) + static inline void ADD_IX_BC(Z80* ctx) { ctx->ADD_IX_RP(0b00); } + static inline void ADD_IX_DE(Z80* ctx) { ctx->ADD_IX_RP(0b01); } + static inline void ADD_IX_IX(Z80* ctx) { ctx->ADD_IX_RP(0b10); } + static inline void ADD_IX_SP(Z80* ctx) { ctx->ADD_IX_RP(0b11); } + inline void ADD_IX_RP(unsigned char rp) { - if (isDebug()) log("[%04X] ADD IX<$%04X>, %s", reg.PC, reg.IX, registerPairDumpIX(rp)); + if (isDebug()) log("[%04X] ADD IX<$%04X>, %s", reg.PC - 2, reg.IX, registerPairDumpIX(rp)); unsigned short nn = getRPIX(rp); setFlagByAdd16(reg.IX, nn); reg.IX += nn; - reg.PC += 2; - return consumeClock(7); + consumeClock(7); } // Add register pair to IY - static inline int ADD_IY_BC(Z80* ctx) { return ctx->ADD_IY_RP(0b00); } - static inline int ADD_IY_DE(Z80* ctx) { return ctx->ADD_IY_RP(0b01); } - static inline int ADD_IY_IY(Z80* ctx) { return ctx->ADD_IY_RP(0b10); } - static inline int ADD_IY_SP(Z80* ctx) { return ctx->ADD_IY_RP(0b11); } - inline int ADD_IY_RP(unsigned char rp) + static inline void ADD_IY_BC(Z80* ctx) { ctx->ADD_IY_RP(0b00); } + static inline void ADD_IY_DE(Z80* ctx) { ctx->ADD_IY_RP(0b01); } + static inline void ADD_IY_IY(Z80* ctx) { ctx->ADD_IY_RP(0b10); } + static inline void ADD_IY_SP(Z80* ctx) { ctx->ADD_IY_RP(0b11); } + inline void ADD_IY_RP(unsigned char rp) { - if (isDebug()) log("[%04X] ADD IY<$%04X>, %s", reg.PC, reg.IY, registerPairDumpIY(rp)); + if (isDebug()) log("[%04X] ADD IY<$%04X>, %s", reg.PC - 2, reg.IY, registerPairDumpIY(rp)); unsigned short nn = getRPIY(rp); setFlagByAdd16(reg.IY, nn); reg.IY += nn; - reg.PC += 2; - return consumeClock(7); + consumeClock(7); } // Increment register pair - static inline int INC_RP_BC(Z80* ctx) { return ctx->INC_RP(0b00); } - static inline int INC_RP_DE(Z80* ctx) { return ctx->INC_RP(0b01); } - static inline int INC_RP_HL(Z80* ctx) { return ctx->INC_RP(0b10); } - static inline int INC_RP_SP(Z80* ctx) { return ctx->INC_RP(0b11); } - inline int INC_RP(unsigned char rp) - { - if (isDebug()) log("[%04X] INC %s", reg.PC, registerPairDump(rp)); - unsigned short nn = getRP(rp); - setRP(rp, nn + 1); - reg.PC++; - return consumeClock(2); + static inline void INC_RP_BC(Z80* ctx) { ctx->INC_RP(0b00); } + static inline void INC_RP_DE(Z80* ctx) { ctx->INC_RP(0b01); } + static inline void INC_RP_HL(Z80* ctx) { ctx->INC_RP(0b10); } + static inline void INC_RP_SP(Z80* ctx) { ctx->INC_RP(0b11); } + inline void INC_RP(unsigned char rp) + { + if (isDebug()) log("[%04X] INC %s", reg.PC - 1, registerPairDump(rp)); + setRP(rp, getRP(rp) + 1); + consumeClock(2); } // Increment IX - static inline int INC_IX_reg_(Z80* ctx) { return ctx->INC_IX_reg(); } - inline int INC_IX_reg() + static inline void INC_IX_reg_(Z80* ctx) { ctx->INC_IX_reg(); } + inline void INC_IX_reg() { - if (isDebug()) log("[%04X] INC IX<$%04X>", reg.PC, reg.IX); + if (isDebug()) log("[%04X] INC IX<$%04X>", reg.PC - 2, reg.IX); reg.IX++; - reg.PC += 2; - return consumeClock(2); + consumeClock(2); } // Increment IY - static inline int INC_IY_reg_(Z80* ctx) { return ctx->INC_IY_reg(); } - inline int INC_IY_reg() + static inline void INC_IY_reg_(Z80* ctx) { ctx->INC_IY_reg(); } + inline void INC_IY_reg() { - if (isDebug()) log("[%04X] INC IY<$%04X>", reg.PC, reg.IY); + if (isDebug()) log("[%04X] INC IY<$%04X>", reg.PC - 2, reg.IY); reg.IY++; - reg.PC += 2; - return consumeClock(2); + consumeClock(2); } // Decrement register pair - static inline int DEC_RP_BC(Z80* ctx) { return ctx->DEC_RP(0b00); } - static inline int DEC_RP_DE(Z80* ctx) { return ctx->DEC_RP(0b01); } - static inline int DEC_RP_HL(Z80* ctx) { return ctx->DEC_RP(0b10); } - static inline int DEC_RP_SP(Z80* ctx) { return ctx->DEC_RP(0b11); } - inline int DEC_RP(unsigned char rp) - { - if (isDebug()) log("[%04X] DEC %s", reg.PC, registerPairDump(rp)); - unsigned short nn = getRP(rp); - setRP(rp, nn - 1); - reg.PC++; - return consumeClock(2); + static inline void DEC_RP_BC(Z80* ctx) { ctx->DEC_RP(0b00); } + static inline void DEC_RP_DE(Z80* ctx) { ctx->DEC_RP(0b01); } + static inline void DEC_RP_HL(Z80* ctx) { ctx->DEC_RP(0b10); } + static inline void DEC_RP_SP(Z80* ctx) { ctx->DEC_RP(0b11); } + inline void DEC_RP(unsigned char rp) + { + if (isDebug()) log("[%04X] DEC %s", reg.PC - 1, registerPairDump(rp)); + setRP(rp, getRP(rp) - 1); + consumeClock(2); } // Decrement IX - static inline int DEC_IX_reg_(Z80* ctx) { return ctx->DEC_IX_reg(); } - inline int DEC_IX_reg() + static inline void DEC_IX_reg_(Z80* ctx) { ctx->DEC_IX_reg(); } + inline void DEC_IX_reg() { - if (isDebug()) log("[%04X] DEC IX<$%04X>", reg.PC, reg.IX); + if (isDebug()) log("[%04X] DEC IX<$%04X>", reg.PC - 2, reg.IX); reg.IX--; - reg.PC += 2; - return consumeClock(2); + consumeClock(2); } // Decrement IY - static inline int DEC_IY_reg_(Z80* ctx) { return ctx->DEC_IY_reg(); } - inline int DEC_IY_reg() + static inline void DEC_IY_reg_(Z80* ctx) { ctx->DEC_IY_reg(); } + inline void DEC_IY_reg() { - if (isDebug()) log("[%04X] DEC IY<$%04X>", reg.PC, reg.IY); + if (isDebug()) log("[%04X] DEC IY<$%04X>", reg.PC - 2, reg.IY); reg.IY--; - reg.PC += 2; - return consumeClock(2); + consumeClock(2); } inline void setFlagBySbc16(unsigned short before, unsigned short subtract) @@ -3720,21 +3360,20 @@ class Z80 } // Subtract register pair from HL with carry - static inline int SBC_HL_BC(Z80* ctx) { return ctx->SBC_HL_RP(0b00); } - static inline int SBC_HL_DE(Z80* ctx) { return ctx->SBC_HL_RP(0b01); } - static inline int SBC_HL_HL(Z80* ctx) { return ctx->SBC_HL_RP(0b10); } - static inline int SBC_HL_SP(Z80* ctx) { return ctx->SBC_HL_RP(0b11); } - inline int SBC_HL_RP(unsigned char rp) + static inline void SBC_HL_BC(Z80* ctx) { ctx->SBC_HL_RP(0b00); } + static inline void SBC_HL_DE(Z80* ctx) { ctx->SBC_HL_RP(0b01); } + static inline void SBC_HL_HL(Z80* ctx) { ctx->SBC_HL_RP(0b10); } + static inline void SBC_HL_SP(Z80* ctx) { ctx->SBC_HL_RP(0b11); } + inline void SBC_HL_RP(unsigned char rp) { - if (isDebug()) log("[%04X] SBC %s, %s ", reg.PC, registerPairDump(0b10), registerPairDump(rp), isFlagC() ? "ON" : "OFF"); + if (isDebug()) log("[%04X] SBC %s, %s ", reg.PC - 2, registerPairDump(0b10), registerPairDump(rp), isFlagC() ? "ON" : "OFF"); unsigned short hl = getHL(); unsigned short nn = getRP(rp); unsigned char c = isFlagC() ? 1 : 0; reg.WZ = hl + 1; setFlagBySbc16(hl, c + nn); setHL(hl - c - nn); - reg.PC += 2; - return consumeClock(7); + consumeClock(7); } inline void setFlagByLogical(bool h) @@ -3748,436 +3387,393 @@ class Z80 setFlagC(false); } - inline void and8(unsigned char n, int pc) + inline void and8(unsigned char n) { reg.pair.A &= n; setFlagByLogical(true); - reg.PC += pc; } - inline void or8(unsigned char n, int pc) + inline void or8(unsigned char n) { reg.pair.A |= n; setFlagByLogical(false); - reg.PC += pc; } - inline void xor8(unsigned char n, int pc) + inline void xor8(unsigned char n) { reg.pair.A ^= n; setFlagByLogical(false); - reg.PC += pc; } // AND Register - static inline int AND_B(Z80* ctx) { return ctx->AND_R(0b000); } - static inline int AND_C(Z80* ctx) { return ctx->AND_R(0b001); } - static inline int AND_D(Z80* ctx) { return ctx->AND_R(0b010); } - static inline int AND_E(Z80* ctx) { return ctx->AND_R(0b011); } - static inline int AND_H(Z80* ctx) { return ctx->AND_R(0b100); } - static inline int AND_L(Z80* ctx) { return ctx->AND_R(0b101); } - static inline int AND_A(Z80* ctx) { return ctx->AND_R(0b111); } - static inline int AND_B_2(Z80* ctx) { return ctx->AND_R(0b000, 2); } - static inline int AND_C_2(Z80* ctx) { return ctx->AND_R(0b001, 2); } - static inline int AND_D_2(Z80* ctx) { return ctx->AND_R(0b010, 2); } - static inline int AND_E_2(Z80* ctx) { return ctx->AND_R(0b011, 2); } - static inline int AND_A_2(Z80* ctx) { return ctx->AND_R(0b111, 2); } - inline int AND_R(unsigned char r, int pc = 1) - { - unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] AND %s, %s", reg.PC, registerDump(0b111), registerDump(r)); - and8(*rp, pc); - return 0; + static inline void AND_B(Z80* ctx) { ctx->AND_R(0b000); } + static inline void AND_C(Z80* ctx) { ctx->AND_R(0b001); } + static inline void AND_D(Z80* ctx) { ctx->AND_R(0b010); } + static inline void AND_E(Z80* ctx) { ctx->AND_R(0b011); } + static inline void AND_H(Z80* ctx) { ctx->AND_R(0b100); } + static inline void AND_L(Z80* ctx) { ctx->AND_R(0b101); } + static inline void AND_A(Z80* ctx) { ctx->AND_R(0b111); } + static inline void AND_B_2(Z80* ctx) { ctx->AND_R(0b000, 2); } + static inline void AND_C_2(Z80* ctx) { ctx->AND_R(0b001, 2); } + static inline void AND_D_2(Z80* ctx) { ctx->AND_R(0b010, 2); } + static inline void AND_E_2(Z80* ctx) { ctx->AND_R(0b011, 2); } + static inline void AND_A_2(Z80* ctx) { ctx->AND_R(0b111, 2); } + inline void AND_R(unsigned char r, int pc = 1) + { + if (isDebug()) log("[%04X] AND %s, %s", reg.PC - pc, registerDump(0b111), registerDump(r)); + and8(getRegister(r)); } // AND with register IXH - static inline int AND_IXH_(Z80* ctx) { return ctx->AND_IXH(); } - inline int AND_IXH() + static inline void AND_IXH_(Z80* ctx) { ctx->AND_IXH(); } + inline void AND_IXH() { - if (isDebug()) log("[%04X] AND %s, IXH<$%02X>", reg.PC, registerDump(0b111), getIXH()); - and8(getIXH(), 2); - return 0; + if (isDebug()) log("[%04X] AND %s, IXH<$%02X>", reg.PC - 2, registerDump(0b111), getIXH()); + and8(getIXH()); } // AND with register IXL - static inline int AND_IXL_(Z80* ctx) { return ctx->AND_IXL(); } - inline int AND_IXL() + static inline void AND_IXL_(Z80* ctx) { ctx->AND_IXL(); } + inline void AND_IXL() { - if (isDebug()) log("[%04X] AND %s, IXL<$%02X>", reg.PC, registerDump(0b111), getIXL()); - and8(getIXL(), 2); - return 0; + if (isDebug()) log("[%04X] AND %s, IXL<$%02X>", reg.PC - 2, registerDump(0b111), getIXL()); + and8(getIXL()); } // AND with register IYH - static inline int AND_IYH_(Z80* ctx) { return ctx->AND_IYH(); } - inline int AND_IYH() + static inline void AND_IYH_(Z80* ctx) { ctx->AND_IYH(); } + inline void AND_IYH() { - if (isDebug()) log("[%04X] AND %s, IYH<$%02X>", reg.PC, registerDump(0b111), getIYH()); - and8(getIYH(), 2); - return 0; + if (isDebug()) log("[%04X] AND %s, IYH<$%02X>", reg.PC - 2, registerDump(0b111), getIYH()); + and8(getIYH()); } // AND with register IYL - static inline int AND_IYL_(Z80* ctx) { return ctx->AND_IYL(); } - inline int AND_IYL() + static inline void AND_IYL_(Z80* ctx) { ctx->AND_IYL(); } + inline void AND_IYL() { - if (isDebug()) log("[%04X] AND %s, IYL<$%02X>", reg.PC, registerDump(0b111), getIYL()); - and8(getIYL(), 2); - return 0; + if (isDebug()) log("[%04X] AND %s, IYL<$%02X>", reg.PC - 2, registerDump(0b111), getIYL()); + and8(getIYL()); } // AND immediate - static inline int AND_N(Z80* ctx) + static inline void AND_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] AND %s, $%02X", ctx->reg.PC, ctx->registerDump(0b111), n); - ctx->and8(n, 2); - return 0; + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] AND %s, $%02X", ctx->reg.PC - 2, ctx->registerDump(0b111), n); + ctx->and8(n); } // AND Memory - static inline int AND_HL(Z80* ctx) + static inline void AND_HL(Z80* ctx) { unsigned short addr = ctx->getHL(); unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] AND %s, (%s) = $%02X", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); - ctx->and8(n, 1); - return 0; + if (ctx->isDebug()) ctx->log("[%04X] AND %s, (%s) = $%02X", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); + ctx->and8(n); } // AND Memory - static inline int AND_IX_(Z80* ctx) { return ctx->AND_IX(); } - inline int AND_IX() + static inline void AND_IX_(Z80* ctx) { ctx->AND_IX(); } + inline void AND_IX() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IX + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] AND %s, (IX+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, reg.pair.A & n); - and8(n, 3); - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IX + d)); + if (isDebug()) log("[%04X] AND %s, (IX+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IX + d), reg.pair.A & n); + and8(n); + consumeClock(3); } // AND Memory - static inline int AND_IY_(Z80* ctx) { return ctx->AND_IY(); } - inline int AND_IY() + static inline void AND_IY_(Z80* ctx) { ctx->AND_IY(); } + inline void AND_IY() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IY + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] AND %s, (IY+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, reg.pair.A & n); - and8(n, 3); - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IY + d)); + if (isDebug()) log("[%04X] AND %s, (IY+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IY + d), reg.pair.A & n); + and8(n); + consumeClock(3); } // OR Register - static inline int OR_B(Z80* ctx) { return ctx->OR_R(0b000); } - static inline int OR_C(Z80* ctx) { return ctx->OR_R(0b001); } - static inline int OR_D(Z80* ctx) { return ctx->OR_R(0b010); } - static inline int OR_E(Z80* ctx) { return ctx->OR_R(0b011); } - static inline int OR_H(Z80* ctx) { return ctx->OR_R(0b100); } - static inline int OR_L(Z80* ctx) { return ctx->OR_R(0b101); } - static inline int OR_A(Z80* ctx) { return ctx->OR_R(0b111); } - static inline int OR_B_2(Z80* ctx) { return ctx->OR_R(0b000, 2); } - static inline int OR_C_2(Z80* ctx) { return ctx->OR_R(0b001, 2); } - static inline int OR_D_2(Z80* ctx) { return ctx->OR_R(0b010, 2); } - static inline int OR_E_2(Z80* ctx) { return ctx->OR_R(0b011, 2); } - static inline int OR_A_2(Z80* ctx) { return ctx->OR_R(0b111, 2); } - inline int OR_R(unsigned char r, int pc = 1) - { - unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] OR %s, %s", reg.PC, registerDump(0b111), registerDump(r)); - or8(*rp, pc); - return 0; + static inline void OR_B(Z80* ctx) { ctx->OR_R(0b000); } + static inline void OR_C(Z80* ctx) { ctx->OR_R(0b001); } + static inline void OR_D(Z80* ctx) { ctx->OR_R(0b010); } + static inline void OR_E(Z80* ctx) { ctx->OR_R(0b011); } + static inline void OR_H(Z80* ctx) { ctx->OR_R(0b100); } + static inline void OR_L(Z80* ctx) { ctx->OR_R(0b101); } + static inline void OR_A(Z80* ctx) { ctx->OR_R(0b111); } + static inline void OR_B_2(Z80* ctx) { ctx->OR_R(0b000, 2); } + static inline void OR_C_2(Z80* ctx) { ctx->OR_R(0b001, 2); } + static inline void OR_D_2(Z80* ctx) { ctx->OR_R(0b010, 2); } + static inline void OR_E_2(Z80* ctx) { ctx->OR_R(0b011, 2); } + static inline void OR_A_2(Z80* ctx) { ctx->OR_R(0b111, 2); } + inline void OR_R(unsigned char r, int pc = 1) + { + if (isDebug()) log("[%04X] OR %s, %s", reg.PC - pc, registerDump(0b111), registerDump(r)); + or8(getRegister(r)); } // OR with register IXH - static inline int OR_IXH_(Z80* ctx) { return ctx->OR_IXH(); } - inline int OR_IXH() + static inline void OR_IXH_(Z80* ctx) { ctx->OR_IXH(); } + inline void OR_IXH() { - if (isDebug()) log("[%04X] OR %s, IXH<$%02X>", reg.PC, registerDump(0b111), getIXH()); - or8(getIXH(), 2); - return 0; + if (isDebug()) log("[%04X] OR %s, IXH<$%02X>", reg.PC - 2, registerDump(0b111), getIXH()); + or8(getIXH()); } // OR with register IXL - static inline int OR_IXL_(Z80* ctx) { return ctx->OR_IXL(); } - inline int OR_IXL() + static inline void OR_IXL_(Z80* ctx) { ctx->OR_IXL(); } + inline void OR_IXL() { - if (isDebug()) log("[%04X] OR %s, IXL<$%02X>", reg.PC, registerDump(0b111), getIXL()); - or8(getIXL(), 2); - return 0; + if (isDebug()) log("[%04X] OR %s, IXL<$%02X>", reg.PC - 2, registerDump(0b111), getIXL()); + or8(getIXL()); } // OR with register IYH - static inline int OR_IYH_(Z80* ctx) { return ctx->OR_IYH(); } - inline int OR_IYH() + static inline void OR_IYH_(Z80* ctx) { ctx->OR_IYH(); } + inline void OR_IYH() { - if (isDebug()) log("[%04X] OR %s, IYH<$%02X>", reg.PC, registerDump(0b111), getIYH()); - or8(getIYH(), 2); - return 0; + if (isDebug()) log("[%04X] OR %s, IYH<$%02X>", reg.PC - 2, registerDump(0b111), getIYH()); + or8(getIYH()); } // OR with register IYL - static inline int OR_IYL_(Z80* ctx) { return ctx->OR_IYL(); } - inline int OR_IYL() + static inline void OR_IYL_(Z80* ctx) { ctx->OR_IYL(); } + inline void OR_IYL() { - if (isDebug()) log("[%04X] OR %s, IYL<$%02X>", reg.PC, registerDump(0b111), getIYL()); - or8(getIYL(), 2); - return 0; + if (isDebug()) log("[%04X] OR %s, IYL<$%02X>", reg.PC - 2, registerDump(0b111), getIYL()); + or8(getIYL()); } // OR immediate - static inline int OR_N(Z80* ctx) + static inline void OR_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] OR %s, $%02X", ctx->reg.PC, ctx->registerDump(0b111), n); - ctx->or8(n, 2); - return 0; + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] OR %s, $%02X", ctx->reg.PC - 2, ctx->registerDump(0b111), n); + ctx->or8(n); } // OR Memory - static inline int OR_HL(Z80* ctx) + static inline void OR_HL(Z80* ctx) { - unsigned short addr = ctx->getHL(); - unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] OR %s, (%s) = $%02X", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), ctx->reg.pair.A | n); - ctx->or8(n, 1); - return 0; + unsigned char n = ctx->readByte(ctx->getHL(), 3); + if (ctx->isDebug()) ctx->log("[%04X] OR %s, (%s) = $%02X", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), ctx->reg.pair.A | n); + ctx->or8(n); } // OR Memory - static inline int OR_IX_(Z80* ctx) { return ctx->OR_IX(); } - inline int OR_IX() + static inline void OR_IX_(Z80* ctx) { ctx->OR_IX(); } + inline void OR_IX() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IX + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] OR %s, (IX+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, reg.pair.A | n); - or8(n, 3); - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IX + d)); + if (isDebug()) log("[%04X] OR %s, (IX+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IX + d), reg.pair.A | n); + or8(n); + consumeClock(3); } // OR Memory - static inline int OR_IY_(Z80* ctx) { return ctx->OR_IY(); } - inline int OR_IY() + static inline void OR_IY_(Z80* ctx) { ctx->OR_IY(); } + inline void OR_IY() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IY + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] OR %s, (IY+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, reg.pair.A | n); - or8(n, 3); - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IY + d)); + if (isDebug()) log("[%04X] OR %s, (IY+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IY + d), reg.pair.A | n); + or8(n); + consumeClock(3); } // XOR Reigster - static inline int XOR_B(Z80* ctx) { return ctx->XOR_R(0b000); } - static inline int XOR_C(Z80* ctx) { return ctx->XOR_R(0b001); } - static inline int XOR_D(Z80* ctx) { return ctx->XOR_R(0b010); } - static inline int XOR_E(Z80* ctx) { return ctx->XOR_R(0b011); } - static inline int XOR_H(Z80* ctx) { return ctx->XOR_R(0b100); } - static inline int XOR_L(Z80* ctx) { return ctx->XOR_R(0b101); } - static inline int XOR_A(Z80* ctx) { return ctx->XOR_R(0b111); } - static inline int XOR_B_2(Z80* ctx) { return ctx->XOR_R(0b000, 2); } - static inline int XOR_C_2(Z80* ctx) { return ctx->XOR_R(0b001, 2); } - static inline int XOR_D_2(Z80* ctx) { return ctx->XOR_R(0b010, 2); } - static inline int XOR_E_2(Z80* ctx) { return ctx->XOR_R(0b011, 2); } - static inline int XOR_A_2(Z80* ctx) { return ctx->XOR_R(0b111, 2); } - inline int XOR_R(unsigned char r, int pc = 1) - { - unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] XOR %s, %s", reg.PC, registerDump(0b111), registerDump(r)); - xor8(*rp, pc); - return 0; + static inline void XOR_B(Z80* ctx) { ctx->XOR_R(0b000); } + static inline void XOR_C(Z80* ctx) { ctx->XOR_R(0b001); } + static inline void XOR_D(Z80* ctx) { ctx->XOR_R(0b010); } + static inline void XOR_E(Z80* ctx) { ctx->XOR_R(0b011); } + static inline void XOR_H(Z80* ctx) { ctx->XOR_R(0b100); } + static inline void XOR_L(Z80* ctx) { ctx->XOR_R(0b101); } + static inline void XOR_A(Z80* ctx) { ctx->XOR_R(0b111); } + static inline void XOR_B_2(Z80* ctx) { ctx->XOR_R(0b000, 2); } + static inline void XOR_C_2(Z80* ctx) { ctx->XOR_R(0b001, 2); } + static inline void XOR_D_2(Z80* ctx) { ctx->XOR_R(0b010, 2); } + static inline void XOR_E_2(Z80* ctx) { ctx->XOR_R(0b011, 2); } + static inline void XOR_A_2(Z80* ctx) { ctx->XOR_R(0b111, 2); } + inline void XOR_R(unsigned char r, int pc = 1) + { + if (isDebug()) log("[%04X] XOR %s, %s", reg.PC - pc, registerDump(0b111), registerDump(r)); + xor8(getRegister(r)); } // XOR with register IXH - static inline int XOR_IXH_(Z80* ctx) { return ctx->XOR_IXH(); } - inline int XOR_IXH() + static inline void XOR_IXH_(Z80* ctx) { ctx->XOR_IXH(); } + inline void XOR_IXH() { - if (isDebug()) log("[%04X] XOR %s, IXH<$%02X>", reg.PC, registerDump(0b111), getIXH()); - xor8(getIXH(), 2); - return 0; + if (isDebug()) log("[%04X] XOR %s, IXH<$%02X>", reg.PC - 2, registerDump(0b111), getIXH()); + xor8(getIXH()); } // XOR with register IXL - static inline int XOR_IXL_(Z80* ctx) { return ctx->XOR_IXL(); } - inline int XOR_IXL() + static inline void XOR_IXL_(Z80* ctx) { ctx->XOR_IXL(); } + inline void XOR_IXL() { - if (isDebug()) log("[%04X] XOR %s, IXL<$%02X>", reg.PC, registerDump(0b111), getIXL()); - xor8(getIXL(), 2); - return 0; + if (isDebug()) log("[%04X] XOR %s, IXL<$%02X>", reg.PC - 2, registerDump(0b111), getIXL()); + xor8(getIXL()); } // XOR with register IYH - static inline int XOR_IYH_(Z80* ctx) { return ctx->XOR_IYH(); } - inline int XOR_IYH() + static inline void XOR_IYH_(Z80* ctx) { ctx->XOR_IYH(); } + inline void XOR_IYH() { - if (isDebug()) log("[%04X] XOR %s, IYH<$%02X>", reg.PC, registerDump(0b111), getIYH()); - xor8(getIYH(), 2); - return 0; + if (isDebug()) log("[%04X] XOR %s, IYH<$%02X>", reg.PC - 2, registerDump(0b111), getIYH()); + xor8(getIYH()); } // XOR with register IYL - static inline int XOR_IYL_(Z80* ctx) { return ctx->XOR_IYL(); } - inline int XOR_IYL() + static inline void XOR_IYL_(Z80* ctx) { ctx->XOR_IYL(); } + inline void XOR_IYL() { - if (isDebug()) log("[%04X] XOR %s, IYL<$%02X>", reg.PC, registerDump(0b111), getIYL()); - xor8(getIYL(), 2); - return 0; + if (isDebug()) log("[%04X] XOR %s, IYL<$%02X>", reg.PC - 2, registerDump(0b111), getIYL()); + xor8(getIYL()); } // XOR immediate - static inline int XOR_N(Z80* ctx) + static inline void XOR_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] XOR %s, $%02X", ctx->reg.PC, ctx->registerDump(0b111), n); - ctx->xor8(n, 2); - return 0; + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] XOR %s, $%02X", ctx->reg.PC - 2, ctx->registerDump(0b111), n); + ctx->xor8(n); } // XOR Memory - static inline int XOR_HL(Z80* ctx) + static inline void XOR_HL(Z80* ctx) { - unsigned short addr = ctx->getHL(); - unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] XOR %s, (%s) = $%02X", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), ctx->reg.pair.A ^ n); - ctx->xor8(n, 1); - return 0; + unsigned char n = ctx->readByte(ctx->getHL(), 3); + if (ctx->isDebug()) ctx->log("[%04X] XOR %s, (%s) = $%02X", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), ctx->reg.pair.A ^ n); + ctx->xor8(n); } // XOR Memory - static inline int XOR_IX_(Z80* ctx) { return ctx->XOR_IX(); } - inline int XOR_IX() + static inline void XOR_IX_(Z80* ctx) { ctx->XOR_IX(); } + inline void XOR_IX() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IX + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] XOR %s, (IX+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, reg.pair.A ^ n); - xor8(n, 3); - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IX + d)); + if (isDebug()) log("[%04X] XOR %s, (IX+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IX + d), reg.pair.A ^ n); + xor8(n); + consumeClock(3); } // XOR Memory - static inline int XOR_IY_(Z80* ctx) { return ctx->XOR_IY(); } - inline int XOR_IY() + static inline void XOR_IY_(Z80* ctx) { ctx->XOR_IY(); } + inline void XOR_IY() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IY + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] XOR %s, (IY+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, reg.pair.A ^ n); - xor8(n, 3); - return consumeClock(3); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IY + d)); + if (isDebug()) log("[%04X] XOR %s, (IY+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IY + d), reg.pair.A ^ n); + xor8(n); + consumeClock(3); } // Complement acc. (1's Comp.) - static inline int CPL(Z80* ctx) + static inline void CPL(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] CPL %s", ctx->reg.PC, ctx->registerDump(0b111)); + if (ctx->isDebug()) ctx->log("[%04X] CPL %s", ctx->reg.PC - 1, ctx->registerDump(0b111)); ctx->reg.pair.A = ~ctx->reg.pair.A; ctx->setFlagH(true); ctx->setFlagN(true); ctx->setFlagXY(ctx->reg.pair.A); - ctx->reg.PC++; - return 0; } // Negate Acc. (2's Comp.) - static inline int NEG_(Z80* ctx) { return ctx->NEG(); } - inline int NEG() + static inline void NEG_(Z80* ctx) { ctx->NEG(); } + inline void NEG() { - if (isDebug()) log("[%04X] NEG %s", reg.PC, registerDump(0b111)); + if (isDebug()) log("[%04X] NEG %s", reg.PC - 2, registerDump(0b111)); unsigned char a = reg.pair.A; reg.pair.A = 0; subtract8(a, 0); - reg.PC += 2; - return 0; } // Complement Carry Flag - static inline int CCF(Z80* ctx) + static inline void CCF(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] CCF %s>", ctx->reg.PC, ctx->isFlagC() ? "ON" : "OFF", !ctx->isFlagC() ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] CCF %s>", ctx->reg.PC - 1, ctx->isFlagC() ? "ON" : "OFF", !ctx->isFlagC() ? "ON" : "OFF"); ctx->setFlagH(ctx->isFlagC()); ctx->setFlagN(false); ctx->setFlagC(!ctx->isFlagC()); ctx->setFlagXY(ctx->reg.pair.A); - ctx->reg.PC++; - return 0; } // Set Carry Flag - static inline int SCF(Z80* ctx) + static inline void SCF(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] SCF ON>", ctx->reg.PC, ctx->isFlagC() ? "ON" : "OFF"); + if (ctx->isDebug()) ctx->log("[%04X] SCF ON>", ctx->reg.PC - 1, ctx->isFlagC() ? "ON" : "OFF"); ctx->setFlagH(false); ctx->setFlagN(false); ctx->setFlagC(true); ctx->setFlagXY(ctx->reg.pair.A); - ctx->reg.PC++; - return 0; } // Test BIT b of register r - static inline int BIT_B_0(Z80* ctx) { return ctx->BIT_R(0b000, 0); } - static inline int BIT_B_1(Z80* ctx) { return ctx->BIT_R(0b000, 1); } - static inline int BIT_B_2(Z80* ctx) { return ctx->BIT_R(0b000, 2); } - static inline int BIT_B_3(Z80* ctx) { return ctx->BIT_R(0b000, 3); } - static inline int BIT_B_4(Z80* ctx) { return ctx->BIT_R(0b000, 4); } - static inline int BIT_B_5(Z80* ctx) { return ctx->BIT_R(0b000, 5); } - static inline int BIT_B_6(Z80* ctx) { return ctx->BIT_R(0b000, 6); } - static inline int BIT_B_7(Z80* ctx) { return ctx->BIT_R(0b000, 7); } - static inline int BIT_C_0(Z80* ctx) { return ctx->BIT_R(0b001, 0); } - static inline int BIT_C_1(Z80* ctx) { return ctx->BIT_R(0b001, 1); } - static inline int BIT_C_2(Z80* ctx) { return ctx->BIT_R(0b001, 2); } - static inline int BIT_C_3(Z80* ctx) { return ctx->BIT_R(0b001, 3); } - static inline int BIT_C_4(Z80* ctx) { return ctx->BIT_R(0b001, 4); } - static inline int BIT_C_5(Z80* ctx) { return ctx->BIT_R(0b001, 5); } - static inline int BIT_C_6(Z80* ctx) { return ctx->BIT_R(0b001, 6); } - static inline int BIT_C_7(Z80* ctx) { return ctx->BIT_R(0b001, 7); } - static inline int BIT_D_0(Z80* ctx) { return ctx->BIT_R(0b010, 0); } - static inline int BIT_D_1(Z80* ctx) { return ctx->BIT_R(0b010, 1); } - static inline int BIT_D_2(Z80* ctx) { return ctx->BIT_R(0b010, 2); } - static inline int BIT_D_3(Z80* ctx) { return ctx->BIT_R(0b010, 3); } - static inline int BIT_D_4(Z80* ctx) { return ctx->BIT_R(0b010, 4); } - static inline int BIT_D_5(Z80* ctx) { return ctx->BIT_R(0b010, 5); } - static inline int BIT_D_6(Z80* ctx) { return ctx->BIT_R(0b010, 6); } - static inline int BIT_D_7(Z80* ctx) { return ctx->BIT_R(0b010, 7); } - static inline int BIT_E_0(Z80* ctx) { return ctx->BIT_R(0b011, 0); } - static inline int BIT_E_1(Z80* ctx) { return ctx->BIT_R(0b011, 1); } - static inline int BIT_E_2(Z80* ctx) { return ctx->BIT_R(0b011, 2); } - static inline int BIT_E_3(Z80* ctx) { return ctx->BIT_R(0b011, 3); } - static inline int BIT_E_4(Z80* ctx) { return ctx->BIT_R(0b011, 4); } - static inline int BIT_E_5(Z80* ctx) { return ctx->BIT_R(0b011, 5); } - static inline int BIT_E_6(Z80* ctx) { return ctx->BIT_R(0b011, 6); } - static inline int BIT_E_7(Z80* ctx) { return ctx->BIT_R(0b011, 7); } - static inline int BIT_H_0(Z80* ctx) { return ctx->BIT_R(0b100, 0); } - static inline int BIT_H_1(Z80* ctx) { return ctx->BIT_R(0b100, 1); } - static inline int BIT_H_2(Z80* ctx) { return ctx->BIT_R(0b100, 2); } - static inline int BIT_H_3(Z80* ctx) { return ctx->BIT_R(0b100, 3); } - static inline int BIT_H_4(Z80* ctx) { return ctx->BIT_R(0b100, 4); } - static inline int BIT_H_5(Z80* ctx) { return ctx->BIT_R(0b100, 5); } - static inline int BIT_H_6(Z80* ctx) { return ctx->BIT_R(0b100, 6); } - static inline int BIT_H_7(Z80* ctx) { return ctx->BIT_R(0b100, 7); } - static inline int BIT_L_0(Z80* ctx) { return ctx->BIT_R(0b101, 0); } - static inline int BIT_L_1(Z80* ctx) { return ctx->BIT_R(0b101, 1); } - static inline int BIT_L_2(Z80* ctx) { return ctx->BIT_R(0b101, 2); } - static inline int BIT_L_3(Z80* ctx) { return ctx->BIT_R(0b101, 3); } - static inline int BIT_L_4(Z80* ctx) { return ctx->BIT_R(0b101, 4); } - static inline int BIT_L_5(Z80* ctx) { return ctx->BIT_R(0b101, 5); } - static inline int BIT_L_6(Z80* ctx) { return ctx->BIT_R(0b101, 6); } - static inline int BIT_L_7(Z80* ctx) { return ctx->BIT_R(0b101, 7); } - static inline int BIT_A_0(Z80* ctx) { return ctx->BIT_R(0b111, 0); } - static inline int BIT_A_1(Z80* ctx) { return ctx->BIT_R(0b111, 1); } - static inline int BIT_A_2(Z80* ctx) { return ctx->BIT_R(0b111, 2); } - static inline int BIT_A_3(Z80* ctx) { return ctx->BIT_R(0b111, 3); } - static inline int BIT_A_4(Z80* ctx) { return ctx->BIT_R(0b111, 4); } - static inline int BIT_A_5(Z80* ctx) { return ctx->BIT_R(0b111, 5); } - static inline int BIT_A_6(Z80* ctx) { return ctx->BIT_R(0b111, 6); } - static inline int BIT_A_7(Z80* ctx) { return ctx->BIT_R(0b111, 7); } - inline int BIT_R(unsigned char r, unsigned char bit) + static inline void BIT_B_0(Z80* ctx) { ctx->BIT_R(0b000, 0); } + static inline void BIT_B_1(Z80* ctx) { ctx->BIT_R(0b000, 1); } + static inline void BIT_B_2(Z80* ctx) { ctx->BIT_R(0b000, 2); } + static inline void BIT_B_3(Z80* ctx) { ctx->BIT_R(0b000, 3); } + static inline void BIT_B_4(Z80* ctx) { ctx->BIT_R(0b000, 4); } + static inline void BIT_B_5(Z80* ctx) { ctx->BIT_R(0b000, 5); } + static inline void BIT_B_6(Z80* ctx) { ctx->BIT_R(0b000, 6); } + static inline void BIT_B_7(Z80* ctx) { ctx->BIT_R(0b000, 7); } + static inline void BIT_C_0(Z80* ctx) { ctx->BIT_R(0b001, 0); } + static inline void BIT_C_1(Z80* ctx) { ctx->BIT_R(0b001, 1); } + static inline void BIT_C_2(Z80* ctx) { ctx->BIT_R(0b001, 2); } + static inline void BIT_C_3(Z80* ctx) { ctx->BIT_R(0b001, 3); } + static inline void BIT_C_4(Z80* ctx) { ctx->BIT_R(0b001, 4); } + static inline void BIT_C_5(Z80* ctx) { ctx->BIT_R(0b001, 5); } + static inline void BIT_C_6(Z80* ctx) { ctx->BIT_R(0b001, 6); } + static inline void BIT_C_7(Z80* ctx) { ctx->BIT_R(0b001, 7); } + static inline void BIT_D_0(Z80* ctx) { ctx->BIT_R(0b010, 0); } + static inline void BIT_D_1(Z80* ctx) { ctx->BIT_R(0b010, 1); } + static inline void BIT_D_2(Z80* ctx) { ctx->BIT_R(0b010, 2); } + static inline void BIT_D_3(Z80* ctx) { ctx->BIT_R(0b010, 3); } + static inline void BIT_D_4(Z80* ctx) { ctx->BIT_R(0b010, 4); } + static inline void BIT_D_5(Z80* ctx) { ctx->BIT_R(0b010, 5); } + static inline void BIT_D_6(Z80* ctx) { ctx->BIT_R(0b010, 6); } + static inline void BIT_D_7(Z80* ctx) { ctx->BIT_R(0b010, 7); } + static inline void BIT_E_0(Z80* ctx) { ctx->BIT_R(0b011, 0); } + static inline void BIT_E_1(Z80* ctx) { ctx->BIT_R(0b011, 1); } + static inline void BIT_E_2(Z80* ctx) { ctx->BIT_R(0b011, 2); } + static inline void BIT_E_3(Z80* ctx) { ctx->BIT_R(0b011, 3); } + static inline void BIT_E_4(Z80* ctx) { ctx->BIT_R(0b011, 4); } + static inline void BIT_E_5(Z80* ctx) { ctx->BIT_R(0b011, 5); } + static inline void BIT_E_6(Z80* ctx) { ctx->BIT_R(0b011, 6); } + static inline void BIT_E_7(Z80* ctx) { ctx->BIT_R(0b011, 7); } + static inline void BIT_H_0(Z80* ctx) { ctx->BIT_R(0b100, 0); } + static inline void BIT_H_1(Z80* ctx) { ctx->BIT_R(0b100, 1); } + static inline void BIT_H_2(Z80* ctx) { ctx->BIT_R(0b100, 2); } + static inline void BIT_H_3(Z80* ctx) { ctx->BIT_R(0b100, 3); } + static inline void BIT_H_4(Z80* ctx) { ctx->BIT_R(0b100, 4); } + static inline void BIT_H_5(Z80* ctx) { ctx->BIT_R(0b100, 5); } + static inline void BIT_H_6(Z80* ctx) { ctx->BIT_R(0b100, 6); } + static inline void BIT_H_7(Z80* ctx) { ctx->BIT_R(0b100, 7); } + static inline void BIT_L_0(Z80* ctx) { ctx->BIT_R(0b101, 0); } + static inline void BIT_L_1(Z80* ctx) { ctx->BIT_R(0b101, 1); } + static inline void BIT_L_2(Z80* ctx) { ctx->BIT_R(0b101, 2); } + static inline void BIT_L_3(Z80* ctx) { ctx->BIT_R(0b101, 3); } + static inline void BIT_L_4(Z80* ctx) { ctx->BIT_R(0b101, 4); } + static inline void BIT_L_5(Z80* ctx) { ctx->BIT_R(0b101, 5); } + static inline void BIT_L_6(Z80* ctx) { ctx->BIT_R(0b101, 6); } + static inline void BIT_L_7(Z80* ctx) { ctx->BIT_R(0b101, 7); } + static inline void BIT_A_0(Z80* ctx) { ctx->BIT_R(0b111, 0); } + static inline void BIT_A_1(Z80* ctx) { ctx->BIT_R(0b111, 1); } + static inline void BIT_A_2(Z80* ctx) { ctx->BIT_R(0b111, 2); } + static inline void BIT_A_3(Z80* ctx) { ctx->BIT_R(0b111, 3); } + static inline void BIT_A_4(Z80* ctx) { ctx->BIT_R(0b111, 4); } + static inline void BIT_A_5(Z80* ctx) { ctx->BIT_R(0b111, 5); } + static inline void BIT_A_6(Z80* ctx) { ctx->BIT_R(0b111, 6); } + static inline void BIT_A_7(Z80* ctx) { ctx->BIT_R(0b111, 7); } + inline void BIT_R(unsigned char r, unsigned char bit) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] BIT %s of bit-%d", reg.PC, registerDump(r), bit); + if (isDebug()) log("[%04X] BIT %s of bit-%d", reg.PC - 2, registerDump(r), bit); unsigned char n = 0; switch (bit) { case 0: n = *rp & 0b00000001; break; @@ -4195,24 +3791,21 @@ class Z80 setFlagH(true); setFlagN(false); setFlagXY(*rp); - reg.PC += 2; - return 0; } - // Test BIT b of lacation (HL) - static inline int BIT_HL_0(Z80* ctx) { return ctx->BIT_HL(0); } - static inline int BIT_HL_1(Z80* ctx) { return ctx->BIT_HL(1); } - static inline int BIT_HL_2(Z80* ctx) { return ctx->BIT_HL(2); } - static inline int BIT_HL_3(Z80* ctx) { return ctx->BIT_HL(3); } - static inline int BIT_HL_4(Z80* ctx) { return ctx->BIT_HL(4); } - static inline int BIT_HL_5(Z80* ctx) { return ctx->BIT_HL(5); } - static inline int BIT_HL_6(Z80* ctx) { return ctx->BIT_HL(6); } - static inline int BIT_HL_7(Z80* ctx) { return ctx->BIT_HL(7); } - inline int BIT_HL(unsigned char bit) + // Test BIT b of location (HL) + static inline void BIT_HL_0(Z80* ctx) { ctx->BIT_HL(0); } + static inline void BIT_HL_1(Z80* ctx) { ctx->BIT_HL(1); } + static inline void BIT_HL_2(Z80* ctx) { ctx->BIT_HL(2); } + static inline void BIT_HL_3(Z80* ctx) { ctx->BIT_HL(3); } + static inline void BIT_HL_4(Z80* ctx) { ctx->BIT_HL(4); } + static inline void BIT_HL_5(Z80* ctx) { ctx->BIT_HL(5); } + static inline void BIT_HL_6(Z80* ctx) { ctx->BIT_HL(6); } + static inline void BIT_HL_7(Z80* ctx) { ctx->BIT_HL(7); } + inline void BIT_HL(unsigned char bit) { - unsigned short addr = getHL(); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] BIT (%s) = $%02X of bit-%d", reg.PC, registerPairDump(0b10), n, bit); + unsigned char n = readByte(getHL()); + if (isDebug()) log("[%04X] BIT (%s) = $%02X of bit-%d", reg.PC - 2, registerPairDump(0b10), n, bit); switch (bit) { case 0: n &= 0b00000001; break; case 1: n &= 0b00000010; break; @@ -4223,30 +3816,27 @@ class Z80 case 6: n &= 0b01000000; break; case 7: n &= 0b10000000; break; } - setFlagZ(n ? false : true); + setFlagZ(!n); setFlagPV(isFlagZ()); setFlagS(!isFlagZ() && 7 == bit); setFlagH(true); setFlagN(false); setFlagXY((reg.WZ & 0xFF00) >> 8); - reg.PC += 2; - return 0; } - // Test BIT b of lacation (IX+d) - static inline int BIT_IX_0(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 0); } - static inline int BIT_IX_1(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 1); } - static inline int BIT_IX_2(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 2); } - static inline int BIT_IX_3(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 3); } - static inline int BIT_IX_4(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 4); } - static inline int BIT_IX_5(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 5); } - static inline int BIT_IX_6(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 6); } - static inline int BIT_IX_7(Z80* ctx, signed char d) { return ctx->BIT_IX(d, 7); } - inline int BIT_IX(signed char d, unsigned char bit) + // Test BIT b of location (IX+d) + static inline void BIT_IX_0(Z80* ctx, signed char d) { ctx->BIT_IX(d, 0); } + static inline void BIT_IX_1(Z80* ctx, signed char d) { ctx->BIT_IX(d, 1); } + static inline void BIT_IX_2(Z80* ctx, signed char d) { ctx->BIT_IX(d, 2); } + static inline void BIT_IX_3(Z80* ctx, signed char d) { ctx->BIT_IX(d, 3); } + static inline void BIT_IX_4(Z80* ctx, signed char d) { ctx->BIT_IX(d, 4); } + static inline void BIT_IX_5(Z80* ctx, signed char d) { ctx->BIT_IX(d, 5); } + static inline void BIT_IX_6(Z80* ctx, signed char d) { ctx->BIT_IX(d, 6); } + static inline void BIT_IX_7(Z80* ctx, signed char d) { ctx->BIT_IX(d, 7); } + inline void BIT_IX(signed char d, unsigned char bit) { - unsigned short addr = (unsigned short)(reg.IX + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] BIT (IX+d<$%04X>) = $%02X of bit-%d", reg.PC, addr, n, bit); + unsigned char n = readByte((unsigned short)(reg.IX + d)); + if (isDebug()) log("[%04X] BIT (IX+d<$%04X>) = $%02X of bit-%d", reg.PC - 4, (unsigned short)(reg.IX + d), n, bit); switch (bit) { case 0: n &= 0b00000001; break; case 1: n &= 0b00000010; break; @@ -4257,30 +3847,27 @@ class Z80 case 6: n &= 0b01000000; break; case 7: n &= 0b10000000; break; } - setFlagZ(n ? false : true); + setFlagZ(!n); setFlagPV(isFlagZ()); setFlagS(!isFlagZ() && 7 == bit); setFlagH(true); setFlagN(false); setFlagXY((reg.WZ & 0xFF00) >> 8); - reg.PC += 4; - return 0; } - // Test BIT b of lacation (IY+d) - static inline int BIT_IY_0(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 0); } - static inline int BIT_IY_1(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 1); } - static inline int BIT_IY_2(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 2); } - static inline int BIT_IY_3(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 3); } - static inline int BIT_IY_4(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 4); } - static inline int BIT_IY_5(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 5); } - static inline int BIT_IY_6(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 6); } - static inline int BIT_IY_7(Z80* ctx, signed char d) { return ctx->BIT_IY(d, 7); } - inline int BIT_IY(signed char d, unsigned char bit) + // Test BIT b of location (IY+d) + static inline void BIT_IY_0(Z80* ctx, signed char d) { ctx->BIT_IY(d, 0); } + static inline void BIT_IY_1(Z80* ctx, signed char d) { ctx->BIT_IY(d, 1); } + static inline void BIT_IY_2(Z80* ctx, signed char d) { ctx->BIT_IY(d, 2); } + static inline void BIT_IY_3(Z80* ctx, signed char d) { ctx->BIT_IY(d, 3); } + static inline void BIT_IY_4(Z80* ctx, signed char d) { ctx->BIT_IY(d, 4); } + static inline void BIT_IY_5(Z80* ctx, signed char d) { ctx->BIT_IY(d, 5); } + static inline void BIT_IY_6(Z80* ctx, signed char d) { ctx->BIT_IY(d, 6); } + static inline void BIT_IY_7(Z80* ctx, signed char d) { ctx->BIT_IY(d, 7); } + inline void BIT_IY(signed char d, unsigned char bit) { - unsigned short addr = (unsigned short)(reg.IY + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] BIT (IY+d<$%04X>) = $%02X of bit-%d", reg.PC, addr, n, bit); + unsigned char n = readByte((unsigned short)(reg.IY + d)); + if (isDebug()) log("[%04X] BIT (IY+d<$%04X>) = $%02X of bit-%d", reg.PC - 4, (unsigned short)(reg.IY + d), n, bit); switch (bit) { case 0: n &= 0b00000001; break; case 1: n &= 0b00000010; break; @@ -4291,77 +3878,75 @@ class Z80 case 6: n &= 0b01000000; break; case 7: n &= 0b10000000; break; } - setFlagZ(n ? false : true); + setFlagZ(!n); setFlagPV(isFlagZ()); setFlagS(!isFlagZ() && 7 == bit); setFlagH(true); setFlagN(false); setFlagXY((reg.WZ & 0xFF00) >> 8); - reg.PC += 4; - return 0; } // SET bit b of register r - static inline int SET_B_0(Z80* ctx) { return ctx->SET_R(0b000, 0); } - static inline int SET_B_1(Z80* ctx) { return ctx->SET_R(0b000, 1); } - static inline int SET_B_2(Z80* ctx) { return ctx->SET_R(0b000, 2); } - static inline int SET_B_3(Z80* ctx) { return ctx->SET_R(0b000, 3); } - static inline int SET_B_4(Z80* ctx) { return ctx->SET_R(0b000, 4); } - static inline int SET_B_5(Z80* ctx) { return ctx->SET_R(0b000, 5); } - static inline int SET_B_6(Z80* ctx) { return ctx->SET_R(0b000, 6); } - static inline int SET_B_7(Z80* ctx) { return ctx->SET_R(0b000, 7); } - static inline int SET_C_0(Z80* ctx) { return ctx->SET_R(0b001, 0); } - static inline int SET_C_1(Z80* ctx) { return ctx->SET_R(0b001, 1); } - static inline int SET_C_2(Z80* ctx) { return ctx->SET_R(0b001, 2); } - static inline int SET_C_3(Z80* ctx) { return ctx->SET_R(0b001, 3); } - static inline int SET_C_4(Z80* ctx) { return ctx->SET_R(0b001, 4); } - static inline int SET_C_5(Z80* ctx) { return ctx->SET_R(0b001, 5); } - static inline int SET_C_6(Z80* ctx) { return ctx->SET_R(0b001, 6); } - static inline int SET_C_7(Z80* ctx) { return ctx->SET_R(0b001, 7); } - static inline int SET_D_0(Z80* ctx) { return ctx->SET_R(0b010, 0); } - static inline int SET_D_1(Z80* ctx) { return ctx->SET_R(0b010, 1); } - static inline int SET_D_2(Z80* ctx) { return ctx->SET_R(0b010, 2); } - static inline int SET_D_3(Z80* ctx) { return ctx->SET_R(0b010, 3); } - static inline int SET_D_4(Z80* ctx) { return ctx->SET_R(0b010, 4); } - static inline int SET_D_5(Z80* ctx) { return ctx->SET_R(0b010, 5); } - static inline int SET_D_6(Z80* ctx) { return ctx->SET_R(0b010, 6); } - static inline int SET_D_7(Z80* ctx) { return ctx->SET_R(0b010, 7); } - static inline int SET_E_0(Z80* ctx) { return ctx->SET_R(0b011, 0); } - static inline int SET_E_1(Z80* ctx) { return ctx->SET_R(0b011, 1); } - static inline int SET_E_2(Z80* ctx) { return ctx->SET_R(0b011, 2); } - static inline int SET_E_3(Z80* ctx) { return ctx->SET_R(0b011, 3); } - static inline int SET_E_4(Z80* ctx) { return ctx->SET_R(0b011, 4); } - static inline int SET_E_5(Z80* ctx) { return ctx->SET_R(0b011, 5); } - static inline int SET_E_6(Z80* ctx) { return ctx->SET_R(0b011, 6); } - static inline int SET_E_7(Z80* ctx) { return ctx->SET_R(0b011, 7); } - static inline int SET_H_0(Z80* ctx) { return ctx->SET_R(0b100, 0); } - static inline int SET_H_1(Z80* ctx) { return ctx->SET_R(0b100, 1); } - static inline int SET_H_2(Z80* ctx) { return ctx->SET_R(0b100, 2); } - static inline int SET_H_3(Z80* ctx) { return ctx->SET_R(0b100, 3); } - static inline int SET_H_4(Z80* ctx) { return ctx->SET_R(0b100, 4); } - static inline int SET_H_5(Z80* ctx) { return ctx->SET_R(0b100, 5); } - static inline int SET_H_6(Z80* ctx) { return ctx->SET_R(0b100, 6); } - static inline int SET_H_7(Z80* ctx) { return ctx->SET_R(0b100, 7); } - static inline int SET_L_0(Z80* ctx) { return ctx->SET_R(0b101, 0); } - static inline int SET_L_1(Z80* ctx) { return ctx->SET_R(0b101, 1); } - static inline int SET_L_2(Z80* ctx) { return ctx->SET_R(0b101, 2); } - static inline int SET_L_3(Z80* ctx) { return ctx->SET_R(0b101, 3); } - static inline int SET_L_4(Z80* ctx) { return ctx->SET_R(0b101, 4); } - static inline int SET_L_5(Z80* ctx) { return ctx->SET_R(0b101, 5); } - static inline int SET_L_6(Z80* ctx) { return ctx->SET_R(0b101, 6); } - static inline int SET_L_7(Z80* ctx) { return ctx->SET_R(0b101, 7); } - static inline int SET_A_0(Z80* ctx) { return ctx->SET_R(0b111, 0); } - static inline int SET_A_1(Z80* ctx) { return ctx->SET_R(0b111, 1); } - static inline int SET_A_2(Z80* ctx) { return ctx->SET_R(0b111, 2); } - static inline int SET_A_3(Z80* ctx) { return ctx->SET_R(0b111, 3); } - static inline int SET_A_4(Z80* ctx) { return ctx->SET_R(0b111, 4); } - static inline int SET_A_5(Z80* ctx) { return ctx->SET_R(0b111, 5); } - static inline int SET_A_6(Z80* ctx) { return ctx->SET_R(0b111, 6); } - static inline int SET_A_7(Z80* ctx) { return ctx->SET_R(0b111, 7); } - inline int SET_R(unsigned char r, unsigned char bit) + static inline void SET_B_0(Z80* ctx) { ctx->SET_R(0b000, 0); } + static inline void SET_B_1(Z80* ctx) { ctx->SET_R(0b000, 1); } + static inline void SET_B_2(Z80* ctx) { ctx->SET_R(0b000, 2); } + static inline void SET_B_3(Z80* ctx) { ctx->SET_R(0b000, 3); } + static inline void SET_B_4(Z80* ctx) { ctx->SET_R(0b000, 4); } + static inline void SET_B_5(Z80* ctx) { ctx->SET_R(0b000, 5); } + static inline void SET_B_6(Z80* ctx) { ctx->SET_R(0b000, 6); } + static inline void SET_B_7(Z80* ctx) { ctx->SET_R(0b000, 7); } + static inline void SET_C_0(Z80* ctx) { ctx->SET_R(0b001, 0); } + static inline void SET_C_1(Z80* ctx) { ctx->SET_R(0b001, 1); } + static inline void SET_C_2(Z80* ctx) { ctx->SET_R(0b001, 2); } + static inline void SET_C_3(Z80* ctx) { ctx->SET_R(0b001, 3); } + static inline void SET_C_4(Z80* ctx) { ctx->SET_R(0b001, 4); } + static inline void SET_C_5(Z80* ctx) { ctx->SET_R(0b001, 5); } + static inline void SET_C_6(Z80* ctx) { ctx->SET_R(0b001, 6); } + static inline void SET_C_7(Z80* ctx) { ctx->SET_R(0b001, 7); } + static inline void SET_D_0(Z80* ctx) { ctx->SET_R(0b010, 0); } + static inline void SET_D_1(Z80* ctx) { ctx->SET_R(0b010, 1); } + static inline void SET_D_2(Z80* ctx) { ctx->SET_R(0b010, 2); } + static inline void SET_D_3(Z80* ctx) { ctx->SET_R(0b010, 3); } + static inline void SET_D_4(Z80* ctx) { ctx->SET_R(0b010, 4); } + static inline void SET_D_5(Z80* ctx) { ctx->SET_R(0b010, 5); } + static inline void SET_D_6(Z80* ctx) { ctx->SET_R(0b010, 6); } + static inline void SET_D_7(Z80* ctx) { ctx->SET_R(0b010, 7); } + static inline void SET_E_0(Z80* ctx) { ctx->SET_R(0b011, 0); } + static inline void SET_E_1(Z80* ctx) { ctx->SET_R(0b011, 1); } + static inline void SET_E_2(Z80* ctx) { ctx->SET_R(0b011, 2); } + static inline void SET_E_3(Z80* ctx) { ctx->SET_R(0b011, 3); } + static inline void SET_E_4(Z80* ctx) { ctx->SET_R(0b011, 4); } + static inline void SET_E_5(Z80* ctx) { ctx->SET_R(0b011, 5); } + static inline void SET_E_6(Z80* ctx) { ctx->SET_R(0b011, 6); } + static inline void SET_E_7(Z80* ctx) { ctx->SET_R(0b011, 7); } + static inline void SET_H_0(Z80* ctx) { ctx->SET_R(0b100, 0); } + static inline void SET_H_1(Z80* ctx) { ctx->SET_R(0b100, 1); } + static inline void SET_H_2(Z80* ctx) { ctx->SET_R(0b100, 2); } + static inline void SET_H_3(Z80* ctx) { ctx->SET_R(0b100, 3); } + static inline void SET_H_4(Z80* ctx) { ctx->SET_R(0b100, 4); } + static inline void SET_H_5(Z80* ctx) { ctx->SET_R(0b100, 5); } + static inline void SET_H_6(Z80* ctx) { ctx->SET_R(0b100, 6); } + static inline void SET_H_7(Z80* ctx) { ctx->SET_R(0b100, 7); } + static inline void SET_L_0(Z80* ctx) { ctx->SET_R(0b101, 0); } + static inline void SET_L_1(Z80* ctx) { ctx->SET_R(0b101, 1); } + static inline void SET_L_2(Z80* ctx) { ctx->SET_R(0b101, 2); } + static inline void SET_L_3(Z80* ctx) { ctx->SET_R(0b101, 3); } + static inline void SET_L_4(Z80* ctx) { ctx->SET_R(0b101, 4); } + static inline void SET_L_5(Z80* ctx) { ctx->SET_R(0b101, 5); } + static inline void SET_L_6(Z80* ctx) { ctx->SET_R(0b101, 6); } + static inline void SET_L_7(Z80* ctx) { ctx->SET_R(0b101, 7); } + static inline void SET_A_0(Z80* ctx) { ctx->SET_R(0b111, 0); } + static inline void SET_A_1(Z80* ctx) { ctx->SET_R(0b111, 1); } + static inline void SET_A_2(Z80* ctx) { ctx->SET_R(0b111, 2); } + static inline void SET_A_3(Z80* ctx) { ctx->SET_R(0b111, 3); } + static inline void SET_A_4(Z80* ctx) { ctx->SET_R(0b111, 4); } + static inline void SET_A_5(Z80* ctx) { ctx->SET_R(0b111, 5); } + static inline void SET_A_6(Z80* ctx) { ctx->SET_R(0b111, 6); } + static inline void SET_A_7(Z80* ctx) { ctx->SET_R(0b111, 7); } + inline void SET_R(unsigned char r, unsigned char bit) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] SET %s of bit-%d", reg.PC, registerDump(r), bit); + if (isDebug()) log("[%04X] SET %s of bit-%d", reg.PC - 2, registerDump(r), bit); switch (bit) { case 0: *rp |= 0b00000001; break; case 1: *rp |= 0b00000010; break; @@ -4372,24 +3957,22 @@ class Z80 case 6: *rp |= 0b01000000; break; case 7: *rp |= 0b10000000; break; } - reg.PC += 2; - return 0; } - // SET bit b of lacation (HL) - static inline int SET_HL_0(Z80* ctx) { return ctx->SET_HL(0); } - static inline int SET_HL_1(Z80* ctx) { return ctx->SET_HL(1); } - static inline int SET_HL_2(Z80* ctx) { return ctx->SET_HL(2); } - static inline int SET_HL_3(Z80* ctx) { return ctx->SET_HL(3); } - static inline int SET_HL_4(Z80* ctx) { return ctx->SET_HL(4); } - static inline int SET_HL_5(Z80* ctx) { return ctx->SET_HL(5); } - static inline int SET_HL_6(Z80* ctx) { return ctx->SET_HL(6); } - static inline int SET_HL_7(Z80* ctx) { return ctx->SET_HL(7); } - inline int SET_HL(unsigned char bit) + // SET bit b of location (HL) + static inline void SET_HL_0(Z80* ctx) { ctx->SET_HL(0); } + static inline void SET_HL_1(Z80* ctx) { ctx->SET_HL(1); } + static inline void SET_HL_2(Z80* ctx) { ctx->SET_HL(2); } + static inline void SET_HL_3(Z80* ctx) { ctx->SET_HL(3); } + static inline void SET_HL_4(Z80* ctx) { ctx->SET_HL(4); } + static inline void SET_HL_5(Z80* ctx) { ctx->SET_HL(5); } + static inline void SET_HL_6(Z80* ctx) { ctx->SET_HL(6); } + static inline void SET_HL_7(Z80* ctx) { ctx->SET_HL(7); } + inline void SET_HL(unsigned char bit) { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SET (%s) = $%02X of bit-%d", reg.PC, registerPairDump(0b10), n, bit); + if (isDebug()) log("[%04X] SET (%s) = $%02X of bit-%d", reg.PC - 2, registerPairDump(0b10), n, bit); switch (bit) { case 0: n |= 0b00000001; break; case 1: n |= 0b00000010; break; @@ -4401,24 +3984,22 @@ class Z80 case 7: n |= 0b10000000; break; } writeByte(addr, n, 3); - reg.PC += 2; - return 0; } - // SET bit b of lacation (IX+d) - static inline int SET_IX_0(Z80* ctx, signed char d) { return ctx->SET_IX(d, 0); } - static inline int SET_IX_1(Z80* ctx, signed char d) { return ctx->SET_IX(d, 1); } - static inline int SET_IX_2(Z80* ctx, signed char d) { return ctx->SET_IX(d, 2); } - static inline int SET_IX_3(Z80* ctx, signed char d) { return ctx->SET_IX(d, 3); } - static inline int SET_IX_4(Z80* ctx, signed char d) { return ctx->SET_IX(d, 4); } - static inline int SET_IX_5(Z80* ctx, signed char d) { return ctx->SET_IX(d, 5); } - static inline int SET_IX_6(Z80* ctx, signed char d) { return ctx->SET_IX(d, 6); } - static inline int SET_IX_7(Z80* ctx, signed char d) { return ctx->SET_IX(d, 7); } - inline int SET_IX(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) + // SET bit b of location (IX+d) + static inline void SET_IX_0(Z80* ctx, signed char d) { ctx->SET_IX(d, 0); } + static inline void SET_IX_1(Z80* ctx, signed char d) { ctx->SET_IX(d, 1); } + static inline void SET_IX_2(Z80* ctx, signed char d) { ctx->SET_IX(d, 2); } + static inline void SET_IX_3(Z80* ctx, signed char d) { ctx->SET_IX(d, 3); } + static inline void SET_IX_4(Z80* ctx, signed char d) { ctx->SET_IX(d, 4); } + static inline void SET_IX_5(Z80* ctx, signed char d) { ctx->SET_IX(d, 5); } + static inline void SET_IX_6(Z80* ctx, signed char d) { ctx->SET_IX(d, 6); } + static inline void SET_IX_7(Z80* ctx, signed char d) { ctx->SET_IX(d, 7); } + inline void SET_IX(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SET (IX+d<$%04X>) = $%02X of bit-%d%s", reg.PC, addr, n, bit, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SET (IX+d<$%04X>) = $%02X of bit-%d%s", reg.PC - 4, addr, n, bit, extraLog ? extraLog : ""); switch (bit) { case 0: n |= 0b00000001; break; case 1: n |= 0b00000010; break; @@ -4431,68 +4012,66 @@ class Z80 } if (rp) *rp = n; writeByte(addr, n, 3); - reg.PC += 4; - return 0; - } - - // SET bit b of lacation (IX+d) with load Reg. - static inline int SET_IX_0_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 0, 0b000); } - static inline int SET_IX_1_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 1, 0b000); } - static inline int SET_IX_2_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 2, 0b000); } - static inline int SET_IX_3_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 3, 0b000); } - static inline int SET_IX_4_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 4, 0b000); } - static inline int SET_IX_5_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 5, 0b000); } - static inline int SET_IX_6_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 6, 0b000); } - static inline int SET_IX_7_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 7, 0b000); } - static inline int SET_IX_0_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 0, 0b001); } - static inline int SET_IX_1_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 1, 0b001); } - static inline int SET_IX_2_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 2, 0b001); } - static inline int SET_IX_3_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 3, 0b001); } - static inline int SET_IX_4_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 4, 0b001); } - static inline int SET_IX_5_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 5, 0b001); } - static inline int SET_IX_6_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 6, 0b001); } - static inline int SET_IX_7_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 7, 0b001); } - static inline int SET_IX_0_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 0, 0b010); } - static inline int SET_IX_1_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 1, 0b010); } - static inline int SET_IX_2_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 2, 0b010); } - static inline int SET_IX_3_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 3, 0b010); } - static inline int SET_IX_4_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 4, 0b010); } - static inline int SET_IX_5_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 5, 0b010); } - static inline int SET_IX_6_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 6, 0b010); } - static inline int SET_IX_7_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 7, 0b010); } - static inline int SET_IX_0_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 0, 0b011); } - static inline int SET_IX_1_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 1, 0b011); } - static inline int SET_IX_2_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 2, 0b011); } - static inline int SET_IX_3_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 3, 0b011); } - static inline int SET_IX_4_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 4, 0b011); } - static inline int SET_IX_5_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 5, 0b011); } - static inline int SET_IX_6_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 6, 0b011); } - static inline int SET_IX_7_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 7, 0b011); } - static inline int SET_IX_0_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 0, 0b100); } - static inline int SET_IX_1_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 1, 0b100); } - static inline int SET_IX_2_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 2, 0b100); } - static inline int SET_IX_3_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 3, 0b100); } - static inline int SET_IX_4_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 4, 0b100); } - static inline int SET_IX_5_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 5, 0b100); } - static inline int SET_IX_6_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 6, 0b100); } - static inline int SET_IX_7_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 7, 0b100); } - static inline int SET_IX_0_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 0, 0b101); } - static inline int SET_IX_1_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 1, 0b101); } - static inline int SET_IX_2_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 2, 0b101); } - static inline int SET_IX_3_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 3, 0b101); } - static inline int SET_IX_4_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 4, 0b101); } - static inline int SET_IX_5_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 5, 0b101); } - static inline int SET_IX_6_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 6, 0b101); } - static inline int SET_IX_7_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 7, 0b101); } - static inline int SET_IX_0_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 0, 0b111); } - static inline int SET_IX_1_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 1, 0b111); } - static inline int SET_IX_2_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 2, 0b111); } - static inline int SET_IX_3_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 3, 0b111); } - static inline int SET_IX_4_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 4, 0b111); } - static inline int SET_IX_5_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 5, 0b111); } - static inline int SET_IX_6_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 6, 0b111); } - static inline int SET_IX_7_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IX_with_LD(d, 7, 0b111); } - inline int SET_IX_with_LD(signed char d, unsigned char bit, unsigned char r) + } + + // SET bit b of location (IX+d) with load Reg. + static inline void SET_IX_0_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 0, 0b000); } + static inline void SET_IX_1_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 1, 0b000); } + static inline void SET_IX_2_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 2, 0b000); } + static inline void SET_IX_3_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 3, 0b000); } + static inline void SET_IX_4_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 4, 0b000); } + static inline void SET_IX_5_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 5, 0b000); } + static inline void SET_IX_6_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 6, 0b000); } + static inline void SET_IX_7_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 7, 0b000); } + static inline void SET_IX_0_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 0, 0b001); } + static inline void SET_IX_1_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 1, 0b001); } + static inline void SET_IX_2_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 2, 0b001); } + static inline void SET_IX_3_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 3, 0b001); } + static inline void SET_IX_4_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 4, 0b001); } + static inline void SET_IX_5_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 5, 0b001); } + static inline void SET_IX_6_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 6, 0b001); } + static inline void SET_IX_7_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 7, 0b001); } + static inline void SET_IX_0_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 0, 0b010); } + static inline void SET_IX_1_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 1, 0b010); } + static inline void SET_IX_2_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 2, 0b010); } + static inline void SET_IX_3_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 3, 0b010); } + static inline void SET_IX_4_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 4, 0b010); } + static inline void SET_IX_5_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 5, 0b010); } + static inline void SET_IX_6_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 6, 0b010); } + static inline void SET_IX_7_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 7, 0b010); } + static inline void SET_IX_0_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 0, 0b011); } + static inline void SET_IX_1_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 1, 0b011); } + static inline void SET_IX_2_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 2, 0b011); } + static inline void SET_IX_3_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 3, 0b011); } + static inline void SET_IX_4_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 4, 0b011); } + static inline void SET_IX_5_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 5, 0b011); } + static inline void SET_IX_6_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 6, 0b011); } + static inline void SET_IX_7_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 7, 0b011); } + static inline void SET_IX_0_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 0, 0b100); } + static inline void SET_IX_1_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 1, 0b100); } + static inline void SET_IX_2_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 2, 0b100); } + static inline void SET_IX_3_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 3, 0b100); } + static inline void SET_IX_4_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 4, 0b100); } + static inline void SET_IX_5_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 5, 0b100); } + static inline void SET_IX_6_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 6, 0b100); } + static inline void SET_IX_7_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 7, 0b100); } + static inline void SET_IX_0_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 0, 0b101); } + static inline void SET_IX_1_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 1, 0b101); } + static inline void SET_IX_2_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 2, 0b101); } + static inline void SET_IX_3_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 3, 0b101); } + static inline void SET_IX_4_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 4, 0b101); } + static inline void SET_IX_5_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 5, 0b101); } + static inline void SET_IX_6_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 6, 0b101); } + static inline void SET_IX_7_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 7, 0b101); } + static inline void SET_IX_0_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 0, 0b111); } + static inline void SET_IX_1_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 1, 0b111); } + static inline void SET_IX_2_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 2, 0b111); } + static inline void SET_IX_3_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 3, 0b111); } + static inline void SET_IX_4_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 4, 0b111); } + static inline void SET_IX_5_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 5, 0b111); } + static inline void SET_IX_6_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 6, 0b111); } + static inline void SET_IX_7_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IX_with_LD(d, 7, 0b111); } + inline void SET_IX_with_LD(signed char d, unsigned char bit, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -4501,23 +4080,23 @@ class Z80 } else { buf[0] = '\0'; } - return SET_IX(d, bit, rp, buf); + SET_IX(d, bit, rp, buf); } - // SET bit b of lacation (IY+d) - static inline int SET_IY_0(Z80* ctx, signed char d) { return ctx->SET_IY(d, 0); } - static inline int SET_IY_1(Z80* ctx, signed char d) { return ctx->SET_IY(d, 1); } - static inline int SET_IY_2(Z80* ctx, signed char d) { return ctx->SET_IY(d, 2); } - static inline int SET_IY_3(Z80* ctx, signed char d) { return ctx->SET_IY(d, 3); } - static inline int SET_IY_4(Z80* ctx, signed char d) { return ctx->SET_IY(d, 4); } - static inline int SET_IY_5(Z80* ctx, signed char d) { return ctx->SET_IY(d, 5); } - static inline int SET_IY_6(Z80* ctx, signed char d) { return ctx->SET_IY(d, 6); } - static inline int SET_IY_7(Z80* ctx, signed char d) { return ctx->SET_IY(d, 7); } - inline int SET_IY(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) + // SET bit b of location (IY+d) + static inline void SET_IY_0(Z80* ctx, signed char d) { ctx->SET_IY(d, 0); } + static inline void SET_IY_1(Z80* ctx, signed char d) { ctx->SET_IY(d, 1); } + static inline void SET_IY_2(Z80* ctx, signed char d) { ctx->SET_IY(d, 2); } + static inline void SET_IY_3(Z80* ctx, signed char d) { ctx->SET_IY(d, 3); } + static inline void SET_IY_4(Z80* ctx, signed char d) { ctx->SET_IY(d, 4); } + static inline void SET_IY_5(Z80* ctx, signed char d) { ctx->SET_IY(d, 5); } + static inline void SET_IY_6(Z80* ctx, signed char d) { ctx->SET_IY(d, 6); } + static inline void SET_IY_7(Z80* ctx, signed char d) { ctx->SET_IY(d, 7); } + inline void SET_IY(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] SET (IY+d<$%04X>) = $%02X of bit-%d%s", reg.PC, addr, n, bit, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] SET (IY+d<$%04X>) = $%02X of bit-%d%s", reg.PC - 4, addr, n, bit, extraLog ? extraLog : ""); switch (bit) { case 0: n |= 0b00000001; break; case 1: n |= 0b00000010; break; @@ -4530,68 +4109,66 @@ class Z80 } if (rp) *rp = n; writeByte(addr, n, 3); - reg.PC += 4; - return 0; - } - - // SET bit b of lacation (IY+d) with load Reg. - static inline int SET_IY_0_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 0, 0b000); } - static inline int SET_IY_1_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 1, 0b000); } - static inline int SET_IY_2_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 2, 0b000); } - static inline int SET_IY_3_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 3, 0b000); } - static inline int SET_IY_4_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 4, 0b000); } - static inline int SET_IY_5_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 5, 0b000); } - static inline int SET_IY_6_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 6, 0b000); } - static inline int SET_IY_7_with_LD_B(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 7, 0b000); } - static inline int SET_IY_0_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 0, 0b001); } - static inline int SET_IY_1_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 1, 0b001); } - static inline int SET_IY_2_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 2, 0b001); } - static inline int SET_IY_3_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 3, 0b001); } - static inline int SET_IY_4_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 4, 0b001); } - static inline int SET_IY_5_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 5, 0b001); } - static inline int SET_IY_6_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 6, 0b001); } - static inline int SET_IY_7_with_LD_C(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 7, 0b001); } - static inline int SET_IY_0_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 0, 0b010); } - static inline int SET_IY_1_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 1, 0b010); } - static inline int SET_IY_2_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 2, 0b010); } - static inline int SET_IY_3_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 3, 0b010); } - static inline int SET_IY_4_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 4, 0b010); } - static inline int SET_IY_5_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 5, 0b010); } - static inline int SET_IY_6_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 6, 0b010); } - static inline int SET_IY_7_with_LD_D(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 7, 0b010); } - static inline int SET_IY_0_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 0, 0b011); } - static inline int SET_IY_1_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 1, 0b011); } - static inline int SET_IY_2_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 2, 0b011); } - static inline int SET_IY_3_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 3, 0b011); } - static inline int SET_IY_4_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 4, 0b011); } - static inline int SET_IY_5_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 5, 0b011); } - static inline int SET_IY_6_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 6, 0b011); } - static inline int SET_IY_7_with_LD_E(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 7, 0b011); } - static inline int SET_IY_0_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 0, 0b100); } - static inline int SET_IY_1_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 1, 0b100); } - static inline int SET_IY_2_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 2, 0b100); } - static inline int SET_IY_3_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 3, 0b100); } - static inline int SET_IY_4_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 4, 0b100); } - static inline int SET_IY_5_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 5, 0b100); } - static inline int SET_IY_6_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 6, 0b100); } - static inline int SET_IY_7_with_LD_H(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 7, 0b100); } - static inline int SET_IY_0_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 0, 0b101); } - static inline int SET_IY_1_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 1, 0b101); } - static inline int SET_IY_2_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 2, 0b101); } - static inline int SET_IY_3_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 3, 0b101); } - static inline int SET_IY_4_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 4, 0b101); } - static inline int SET_IY_5_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 5, 0b101); } - static inline int SET_IY_6_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 6, 0b101); } - static inline int SET_IY_7_with_LD_L(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 7, 0b101); } - static inline int SET_IY_0_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 0, 0b111); } - static inline int SET_IY_1_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 1, 0b111); } - static inline int SET_IY_2_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 2, 0b111); } - static inline int SET_IY_3_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 3, 0b111); } - static inline int SET_IY_4_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 4, 0b111); } - static inline int SET_IY_5_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 5, 0b111); } - static inline int SET_IY_6_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 6, 0b111); } - static inline int SET_IY_7_with_LD_A(Z80* ctx, signed char d) { return ctx->SET_IY_with_LD(d, 7, 0b111); } - inline int SET_IY_with_LD(signed char d, unsigned char bit, unsigned char r) + } + + // SET bit b of location (IY+d) with load Reg. + static inline void SET_IY_0_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 0, 0b000); } + static inline void SET_IY_1_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 1, 0b000); } + static inline void SET_IY_2_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 2, 0b000); } + static inline void SET_IY_3_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 3, 0b000); } + static inline void SET_IY_4_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 4, 0b000); } + static inline void SET_IY_5_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 5, 0b000); } + static inline void SET_IY_6_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 6, 0b000); } + static inline void SET_IY_7_with_LD_B(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 7, 0b000); } + static inline void SET_IY_0_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 0, 0b001); } + static inline void SET_IY_1_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 1, 0b001); } + static inline void SET_IY_2_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 2, 0b001); } + static inline void SET_IY_3_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 3, 0b001); } + static inline void SET_IY_4_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 4, 0b001); } + static inline void SET_IY_5_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 5, 0b001); } + static inline void SET_IY_6_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 6, 0b001); } + static inline void SET_IY_7_with_LD_C(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 7, 0b001); } + static inline void SET_IY_0_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 0, 0b010); } + static inline void SET_IY_1_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 1, 0b010); } + static inline void SET_IY_2_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 2, 0b010); } + static inline void SET_IY_3_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 3, 0b010); } + static inline void SET_IY_4_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 4, 0b010); } + static inline void SET_IY_5_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 5, 0b010); } + static inline void SET_IY_6_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 6, 0b010); } + static inline void SET_IY_7_with_LD_D(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 7, 0b010); } + static inline void SET_IY_0_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 0, 0b011); } + static inline void SET_IY_1_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 1, 0b011); } + static inline void SET_IY_2_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 2, 0b011); } + static inline void SET_IY_3_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 3, 0b011); } + static inline void SET_IY_4_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 4, 0b011); } + static inline void SET_IY_5_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 5, 0b011); } + static inline void SET_IY_6_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 6, 0b011); } + static inline void SET_IY_7_with_LD_E(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 7, 0b011); } + static inline void SET_IY_0_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 0, 0b100); } + static inline void SET_IY_1_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 1, 0b100); } + static inline void SET_IY_2_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 2, 0b100); } + static inline void SET_IY_3_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 3, 0b100); } + static inline void SET_IY_4_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 4, 0b100); } + static inline void SET_IY_5_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 5, 0b100); } + static inline void SET_IY_6_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 6, 0b100); } + static inline void SET_IY_7_with_LD_H(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 7, 0b100); } + static inline void SET_IY_0_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 0, 0b101); } + static inline void SET_IY_1_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 1, 0b101); } + static inline void SET_IY_2_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 2, 0b101); } + static inline void SET_IY_3_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 3, 0b101); } + static inline void SET_IY_4_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 4, 0b101); } + static inline void SET_IY_5_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 5, 0b101); } + static inline void SET_IY_6_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 6, 0b101); } + static inline void SET_IY_7_with_LD_L(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 7, 0b101); } + static inline void SET_IY_0_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 0, 0b111); } + static inline void SET_IY_1_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 1, 0b111); } + static inline void SET_IY_2_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 2, 0b111); } + static inline void SET_IY_3_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 3, 0b111); } + static inline void SET_IY_4_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 4, 0b111); } + static inline void SET_IY_5_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 5, 0b111); } + static inline void SET_IY_6_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 6, 0b111); } + static inline void SET_IY_7_with_LD_A(Z80* ctx, signed char d) { ctx->SET_IY_with_LD(d, 7, 0b111); } + inline void SET_IY_with_LD(signed char d, unsigned char bit, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -4600,70 +4177,70 @@ class Z80 } else { buf[0] = '\0'; } - return SET_IY(d, bit, rp, buf); + SET_IY(d, bit, rp, buf); } // RESET bit b of register r - static inline int RES_B_0(Z80* ctx) { return ctx->RES_R(0b000, 0); } - static inline int RES_B_1(Z80* ctx) { return ctx->RES_R(0b000, 1); } - static inline int RES_B_2(Z80* ctx) { return ctx->RES_R(0b000, 2); } - static inline int RES_B_3(Z80* ctx) { return ctx->RES_R(0b000, 3); } - static inline int RES_B_4(Z80* ctx) { return ctx->RES_R(0b000, 4); } - static inline int RES_B_5(Z80* ctx) { return ctx->RES_R(0b000, 5); } - static inline int RES_B_6(Z80* ctx) { return ctx->RES_R(0b000, 6); } - static inline int RES_B_7(Z80* ctx) { return ctx->RES_R(0b000, 7); } - static inline int RES_C_0(Z80* ctx) { return ctx->RES_R(0b001, 0); } - static inline int RES_C_1(Z80* ctx) { return ctx->RES_R(0b001, 1); } - static inline int RES_C_2(Z80* ctx) { return ctx->RES_R(0b001, 2); } - static inline int RES_C_3(Z80* ctx) { return ctx->RES_R(0b001, 3); } - static inline int RES_C_4(Z80* ctx) { return ctx->RES_R(0b001, 4); } - static inline int RES_C_5(Z80* ctx) { return ctx->RES_R(0b001, 5); } - static inline int RES_C_6(Z80* ctx) { return ctx->RES_R(0b001, 6); } - static inline int RES_C_7(Z80* ctx) { return ctx->RES_R(0b001, 7); } - static inline int RES_D_0(Z80* ctx) { return ctx->RES_R(0b010, 0); } - static inline int RES_D_1(Z80* ctx) { return ctx->RES_R(0b010, 1); } - static inline int RES_D_2(Z80* ctx) { return ctx->RES_R(0b010, 2); } - static inline int RES_D_3(Z80* ctx) { return ctx->RES_R(0b010, 3); } - static inline int RES_D_4(Z80* ctx) { return ctx->RES_R(0b010, 4); } - static inline int RES_D_5(Z80* ctx) { return ctx->RES_R(0b010, 5); } - static inline int RES_D_6(Z80* ctx) { return ctx->RES_R(0b010, 6); } - static inline int RES_D_7(Z80* ctx) { return ctx->RES_R(0b010, 7); } - static inline int RES_E_0(Z80* ctx) { return ctx->RES_R(0b011, 0); } - static inline int RES_E_1(Z80* ctx) { return ctx->RES_R(0b011, 1); } - static inline int RES_E_2(Z80* ctx) { return ctx->RES_R(0b011, 2); } - static inline int RES_E_3(Z80* ctx) { return ctx->RES_R(0b011, 3); } - static inline int RES_E_4(Z80* ctx) { return ctx->RES_R(0b011, 4); } - static inline int RES_E_5(Z80* ctx) { return ctx->RES_R(0b011, 5); } - static inline int RES_E_6(Z80* ctx) { return ctx->RES_R(0b011, 6); } - static inline int RES_E_7(Z80* ctx) { return ctx->RES_R(0b011, 7); } - static inline int RES_H_0(Z80* ctx) { return ctx->RES_R(0b100, 0); } - static inline int RES_H_1(Z80* ctx) { return ctx->RES_R(0b100, 1); } - static inline int RES_H_2(Z80* ctx) { return ctx->RES_R(0b100, 2); } - static inline int RES_H_3(Z80* ctx) { return ctx->RES_R(0b100, 3); } - static inline int RES_H_4(Z80* ctx) { return ctx->RES_R(0b100, 4); } - static inline int RES_H_5(Z80* ctx) { return ctx->RES_R(0b100, 5); } - static inline int RES_H_6(Z80* ctx) { return ctx->RES_R(0b100, 6); } - static inline int RES_H_7(Z80* ctx) { return ctx->RES_R(0b100, 7); } - static inline int RES_L_0(Z80* ctx) { return ctx->RES_R(0b101, 0); } - static inline int RES_L_1(Z80* ctx) { return ctx->RES_R(0b101, 1); } - static inline int RES_L_2(Z80* ctx) { return ctx->RES_R(0b101, 2); } - static inline int RES_L_3(Z80* ctx) { return ctx->RES_R(0b101, 3); } - static inline int RES_L_4(Z80* ctx) { return ctx->RES_R(0b101, 4); } - static inline int RES_L_5(Z80* ctx) { return ctx->RES_R(0b101, 5); } - static inline int RES_L_6(Z80* ctx) { return ctx->RES_R(0b101, 6); } - static inline int RES_L_7(Z80* ctx) { return ctx->RES_R(0b101, 7); } - static inline int RES_A_0(Z80* ctx) { return ctx->RES_R(0b111, 0); } - static inline int RES_A_1(Z80* ctx) { return ctx->RES_R(0b111, 1); } - static inline int RES_A_2(Z80* ctx) { return ctx->RES_R(0b111, 2); } - static inline int RES_A_3(Z80* ctx) { return ctx->RES_R(0b111, 3); } - static inline int RES_A_4(Z80* ctx) { return ctx->RES_R(0b111, 4); } - static inline int RES_A_5(Z80* ctx) { return ctx->RES_R(0b111, 5); } - static inline int RES_A_6(Z80* ctx) { return ctx->RES_R(0b111, 6); } - static inline int RES_A_7(Z80* ctx) { return ctx->RES_R(0b111, 7); } - inline int RES_R(unsigned char r, unsigned char bit) + static inline void RES_B_0(Z80* ctx) { ctx->RES_R(0b000, 0); } + static inline void RES_B_1(Z80* ctx) { ctx->RES_R(0b000, 1); } + static inline void RES_B_2(Z80* ctx) { ctx->RES_R(0b000, 2); } + static inline void RES_B_3(Z80* ctx) { ctx->RES_R(0b000, 3); } + static inline void RES_B_4(Z80* ctx) { ctx->RES_R(0b000, 4); } + static inline void RES_B_5(Z80* ctx) { ctx->RES_R(0b000, 5); } + static inline void RES_B_6(Z80* ctx) { ctx->RES_R(0b000, 6); } + static inline void RES_B_7(Z80* ctx) { ctx->RES_R(0b000, 7); } + static inline void RES_C_0(Z80* ctx) { ctx->RES_R(0b001, 0); } + static inline void RES_C_1(Z80* ctx) { ctx->RES_R(0b001, 1); } + static inline void RES_C_2(Z80* ctx) { ctx->RES_R(0b001, 2); } + static inline void RES_C_3(Z80* ctx) { ctx->RES_R(0b001, 3); } + static inline void RES_C_4(Z80* ctx) { ctx->RES_R(0b001, 4); } + static inline void RES_C_5(Z80* ctx) { ctx->RES_R(0b001, 5); } + static inline void RES_C_6(Z80* ctx) { ctx->RES_R(0b001, 6); } + static inline void RES_C_7(Z80* ctx) { ctx->RES_R(0b001, 7); } + static inline void RES_D_0(Z80* ctx) { ctx->RES_R(0b010, 0); } + static inline void RES_D_1(Z80* ctx) { ctx->RES_R(0b010, 1); } + static inline void RES_D_2(Z80* ctx) { ctx->RES_R(0b010, 2); } + static inline void RES_D_3(Z80* ctx) { ctx->RES_R(0b010, 3); } + static inline void RES_D_4(Z80* ctx) { ctx->RES_R(0b010, 4); } + static inline void RES_D_5(Z80* ctx) { ctx->RES_R(0b010, 5); } + static inline void RES_D_6(Z80* ctx) { ctx->RES_R(0b010, 6); } + static inline void RES_D_7(Z80* ctx) { ctx->RES_R(0b010, 7); } + static inline void RES_E_0(Z80* ctx) { ctx->RES_R(0b011, 0); } + static inline void RES_E_1(Z80* ctx) { ctx->RES_R(0b011, 1); } + static inline void RES_E_2(Z80* ctx) { ctx->RES_R(0b011, 2); } + static inline void RES_E_3(Z80* ctx) { ctx->RES_R(0b011, 3); } + static inline void RES_E_4(Z80* ctx) { ctx->RES_R(0b011, 4); } + static inline void RES_E_5(Z80* ctx) { ctx->RES_R(0b011, 5); } + static inline void RES_E_6(Z80* ctx) { ctx->RES_R(0b011, 6); } + static inline void RES_E_7(Z80* ctx) { ctx->RES_R(0b011, 7); } + static inline void RES_H_0(Z80* ctx) { ctx->RES_R(0b100, 0); } + static inline void RES_H_1(Z80* ctx) { ctx->RES_R(0b100, 1); } + static inline void RES_H_2(Z80* ctx) { ctx->RES_R(0b100, 2); } + static inline void RES_H_3(Z80* ctx) { ctx->RES_R(0b100, 3); } + static inline void RES_H_4(Z80* ctx) { ctx->RES_R(0b100, 4); } + static inline void RES_H_5(Z80* ctx) { ctx->RES_R(0b100, 5); } + static inline void RES_H_6(Z80* ctx) { ctx->RES_R(0b100, 6); } + static inline void RES_H_7(Z80* ctx) { ctx->RES_R(0b100, 7); } + static inline void RES_L_0(Z80* ctx) { ctx->RES_R(0b101, 0); } + static inline void RES_L_1(Z80* ctx) { ctx->RES_R(0b101, 1); } + static inline void RES_L_2(Z80* ctx) { ctx->RES_R(0b101, 2); } + static inline void RES_L_3(Z80* ctx) { ctx->RES_R(0b101, 3); } + static inline void RES_L_4(Z80* ctx) { ctx->RES_R(0b101, 4); } + static inline void RES_L_5(Z80* ctx) { ctx->RES_R(0b101, 5); } + static inline void RES_L_6(Z80* ctx) { ctx->RES_R(0b101, 6); } + static inline void RES_L_7(Z80* ctx) { ctx->RES_R(0b101, 7); } + static inline void RES_A_0(Z80* ctx) { ctx->RES_R(0b111, 0); } + static inline void RES_A_1(Z80* ctx) { ctx->RES_R(0b111, 1); } + static inline void RES_A_2(Z80* ctx) { ctx->RES_R(0b111, 2); } + static inline void RES_A_3(Z80* ctx) { ctx->RES_R(0b111, 3); } + static inline void RES_A_4(Z80* ctx) { ctx->RES_R(0b111, 4); } + static inline void RES_A_5(Z80* ctx) { ctx->RES_R(0b111, 5); } + static inline void RES_A_6(Z80* ctx) { ctx->RES_R(0b111, 6); } + static inline void RES_A_7(Z80* ctx) { ctx->RES_R(0b111, 7); } + inline void RES_R(unsigned char r, unsigned char bit) { unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] RES %s of bit-%d", reg.PC, registerDump(r), bit); + if (isDebug()) log("[%04X] RES %s of bit-%d", reg.PC - 2, registerDump(r), bit); switch (bit) { case 0: *rp &= 0b11111110; break; case 1: *rp &= 0b11111101; break; @@ -4674,24 +4251,22 @@ class Z80 case 6: *rp &= 0b10111111; break; case 7: *rp &= 0b01111111; break; } - reg.PC += 2; - return 0; } - // RESET bit b of lacation (HL) - static inline int RES_HL_0(Z80* ctx) { return ctx->RES_HL(0); } - static inline int RES_HL_1(Z80* ctx) { return ctx->RES_HL(1); } - static inline int RES_HL_2(Z80* ctx) { return ctx->RES_HL(2); } - static inline int RES_HL_3(Z80* ctx) { return ctx->RES_HL(3); } - static inline int RES_HL_4(Z80* ctx) { return ctx->RES_HL(4); } - static inline int RES_HL_5(Z80* ctx) { return ctx->RES_HL(5); } - static inline int RES_HL_6(Z80* ctx) { return ctx->RES_HL(6); } - static inline int RES_HL_7(Z80* ctx) { return ctx->RES_HL(7); } - inline int RES_HL(unsigned char bit) + // RESET bit b of location (HL) + static inline void RES_HL_0(Z80* ctx) { ctx->RES_HL(0); } + static inline void RES_HL_1(Z80* ctx) { ctx->RES_HL(1); } + static inline void RES_HL_2(Z80* ctx) { ctx->RES_HL(2); } + static inline void RES_HL_3(Z80* ctx) { ctx->RES_HL(3); } + static inline void RES_HL_4(Z80* ctx) { ctx->RES_HL(4); } + static inline void RES_HL_5(Z80* ctx) { ctx->RES_HL(5); } + static inline void RES_HL_6(Z80* ctx) { ctx->RES_HL(6); } + static inline void RES_HL_7(Z80* ctx) { ctx->RES_HL(7); } + inline void RES_HL(unsigned char bit) { unsigned short addr = getHL(); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RES (%s) = $%02X of bit-%d", reg.PC, registerPairDump(0b10), n, bit); + if (isDebug()) log("[%04X] RES (%s) = $%02X of bit-%d", reg.PC - 2, registerPairDump(0b10), n, bit); switch (bit) { case 0: n &= 0b11111110; break; case 1: n &= 0b11111101; break; @@ -4703,24 +4278,22 @@ class Z80 case 7: n &= 0b01111111; break; } writeByte(addr, n, 3); - reg.PC += 2; - return 0; } - // RESET bit b of lacation (IX+d) - static inline int RES_IX_0(Z80* ctx, signed char d) { return ctx->RES_IX(d, 0); } - static inline int RES_IX_1(Z80* ctx, signed char d) { return ctx->RES_IX(d, 1); } - static inline int RES_IX_2(Z80* ctx, signed char d) { return ctx->RES_IX(d, 2); } - static inline int RES_IX_3(Z80* ctx, signed char d) { return ctx->RES_IX(d, 3); } - static inline int RES_IX_4(Z80* ctx, signed char d) { return ctx->RES_IX(d, 4); } - static inline int RES_IX_5(Z80* ctx, signed char d) { return ctx->RES_IX(d, 5); } - static inline int RES_IX_6(Z80* ctx, signed char d) { return ctx->RES_IX(d, 6); } - static inline int RES_IX_7(Z80* ctx, signed char d) { return ctx->RES_IX(d, 7); } - inline int RES_IX(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) + // RESET bit b of location (IX+d) + static inline void RES_IX_0(Z80* ctx, signed char d) { ctx->RES_IX(d, 0); } + static inline void RES_IX_1(Z80* ctx, signed char d) { ctx->RES_IX(d, 1); } + static inline void RES_IX_2(Z80* ctx, signed char d) { ctx->RES_IX(d, 2); } + static inline void RES_IX_3(Z80* ctx, signed char d) { ctx->RES_IX(d, 3); } + static inline void RES_IX_4(Z80* ctx, signed char d) { ctx->RES_IX(d, 4); } + static inline void RES_IX_5(Z80* ctx, signed char d) { ctx->RES_IX(d, 5); } + static inline void RES_IX_6(Z80* ctx, signed char d) { ctx->RES_IX(d, 6); } + static inline void RES_IX_7(Z80* ctx, signed char d) { ctx->RES_IX(d, 7); } + inline void RES_IX(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IX + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RES (IX+d<$%04X>) = $%02X of bit-%d%s", reg.PC, addr, n, bit, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RES (IX+d<$%04X>) = $%02X of bit-%d%s", reg.PC - 4, addr, n, bit, extraLog ? extraLog : ""); switch (bit) { case 0: n &= 0b11111110; break; case 1: n &= 0b11111101; break; @@ -4733,68 +4306,66 @@ class Z80 } if (rp) *rp = n; writeByte(addr, n, 3); - reg.PC += 4; - return 0; - } - - // RESET bit b of lacation (IX+d) with load Reg. - static inline int RES_IX_0_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 0, 0b000); } - static inline int RES_IX_1_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 1, 0b000); } - static inline int RES_IX_2_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 2, 0b000); } - static inline int RES_IX_3_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 3, 0b000); } - static inline int RES_IX_4_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 4, 0b000); } - static inline int RES_IX_5_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 5, 0b000); } - static inline int RES_IX_6_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 6, 0b000); } - static inline int RES_IX_7_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 7, 0b000); } - static inline int RES_IX_0_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 0, 0b001); } - static inline int RES_IX_1_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 1, 0b001); } - static inline int RES_IX_2_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 2, 0b001); } - static inline int RES_IX_3_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 3, 0b001); } - static inline int RES_IX_4_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 4, 0b001); } - static inline int RES_IX_5_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 5, 0b001); } - static inline int RES_IX_6_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 6, 0b001); } - static inline int RES_IX_7_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 7, 0b001); } - static inline int RES_IX_0_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 0, 0b010); } - static inline int RES_IX_1_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 1, 0b010); } - static inline int RES_IX_2_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 2, 0b010); } - static inline int RES_IX_3_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 3, 0b010); } - static inline int RES_IX_4_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 4, 0b010); } - static inline int RES_IX_5_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 5, 0b010); } - static inline int RES_IX_6_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 6, 0b010); } - static inline int RES_IX_7_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 7, 0b010); } - static inline int RES_IX_0_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 0, 0b011); } - static inline int RES_IX_1_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 1, 0b011); } - static inline int RES_IX_2_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 2, 0b011); } - static inline int RES_IX_3_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 3, 0b011); } - static inline int RES_IX_4_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 4, 0b011); } - static inline int RES_IX_5_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 5, 0b011); } - static inline int RES_IX_6_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 6, 0b011); } - static inline int RES_IX_7_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 7, 0b011); } - static inline int RES_IX_0_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 0, 0b100); } - static inline int RES_IX_1_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 1, 0b100); } - static inline int RES_IX_2_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 2, 0b100); } - static inline int RES_IX_3_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 3, 0b100); } - static inline int RES_IX_4_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 4, 0b100); } - static inline int RES_IX_5_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 5, 0b100); } - static inline int RES_IX_6_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 6, 0b100); } - static inline int RES_IX_7_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 7, 0b100); } - static inline int RES_IX_0_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 0, 0b101); } - static inline int RES_IX_1_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 1, 0b101); } - static inline int RES_IX_2_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 2, 0b101); } - static inline int RES_IX_3_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 3, 0b101); } - static inline int RES_IX_4_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 4, 0b101); } - static inline int RES_IX_5_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 5, 0b101); } - static inline int RES_IX_6_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 6, 0b101); } - static inline int RES_IX_7_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 7, 0b101); } - static inline int RES_IX_0_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 0, 0b111); } - static inline int RES_IX_1_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 1, 0b111); } - static inline int RES_IX_2_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 2, 0b111); } - static inline int RES_IX_3_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 3, 0b111); } - static inline int RES_IX_4_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 4, 0b111); } - static inline int RES_IX_5_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 5, 0b111); } - static inline int RES_IX_6_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 6, 0b111); } - static inline int RES_IX_7_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IX_with_LD(d, 7, 0b111); } - inline int RES_IX_with_LD(signed char d, unsigned char bit, unsigned char r) + } + + // RESET bit b of location (IX+d) with load Reg. + static inline void RES_IX_0_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 0, 0b000); } + static inline void RES_IX_1_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 1, 0b000); } + static inline void RES_IX_2_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 2, 0b000); } + static inline void RES_IX_3_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 3, 0b000); } + static inline void RES_IX_4_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 4, 0b000); } + static inline void RES_IX_5_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 5, 0b000); } + static inline void RES_IX_6_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 6, 0b000); } + static inline void RES_IX_7_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 7, 0b000); } + static inline void RES_IX_0_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 0, 0b001); } + static inline void RES_IX_1_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 1, 0b001); } + static inline void RES_IX_2_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 2, 0b001); } + static inline void RES_IX_3_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 3, 0b001); } + static inline void RES_IX_4_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 4, 0b001); } + static inline void RES_IX_5_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 5, 0b001); } + static inline void RES_IX_6_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 6, 0b001); } + static inline void RES_IX_7_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 7, 0b001); } + static inline void RES_IX_0_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 0, 0b010); } + static inline void RES_IX_1_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 1, 0b010); } + static inline void RES_IX_2_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 2, 0b010); } + static inline void RES_IX_3_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 3, 0b010); } + static inline void RES_IX_4_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 4, 0b010); } + static inline void RES_IX_5_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 5, 0b010); } + static inline void RES_IX_6_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 6, 0b010); } + static inline void RES_IX_7_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 7, 0b010); } + static inline void RES_IX_0_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 0, 0b011); } + static inline void RES_IX_1_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 1, 0b011); } + static inline void RES_IX_2_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 2, 0b011); } + static inline void RES_IX_3_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 3, 0b011); } + static inline void RES_IX_4_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 4, 0b011); } + static inline void RES_IX_5_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 5, 0b011); } + static inline void RES_IX_6_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 6, 0b011); } + static inline void RES_IX_7_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 7, 0b011); } + static inline void RES_IX_0_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 0, 0b100); } + static inline void RES_IX_1_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 1, 0b100); } + static inline void RES_IX_2_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 2, 0b100); } + static inline void RES_IX_3_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 3, 0b100); } + static inline void RES_IX_4_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 4, 0b100); } + static inline void RES_IX_5_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 5, 0b100); } + static inline void RES_IX_6_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 6, 0b100); } + static inline void RES_IX_7_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 7, 0b100); } + static inline void RES_IX_0_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 0, 0b101); } + static inline void RES_IX_1_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 1, 0b101); } + static inline void RES_IX_2_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 2, 0b101); } + static inline void RES_IX_3_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 3, 0b101); } + static inline void RES_IX_4_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 4, 0b101); } + static inline void RES_IX_5_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 5, 0b101); } + static inline void RES_IX_6_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 6, 0b101); } + static inline void RES_IX_7_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 7, 0b101); } + static inline void RES_IX_0_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 0, 0b111); } + static inline void RES_IX_1_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 1, 0b111); } + static inline void RES_IX_2_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 2, 0b111); } + static inline void RES_IX_3_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 3, 0b111); } + static inline void RES_IX_4_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 4, 0b111); } + static inline void RES_IX_5_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 5, 0b111); } + static inline void RES_IX_6_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 6, 0b111); } + static inline void RES_IX_7_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IX_with_LD(d, 7, 0b111); } + inline void RES_IX_with_LD(signed char d, unsigned char bit, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -4803,67 +4374,67 @@ class Z80 } else { buf[0] = '\0'; } - return RES_IX(d, bit, rp, buf); - } - - // RESET bit b of lacation (IY+d) with load Reg. - static inline int RES_IY_0_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 0, 0b000); } - static inline int RES_IY_1_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 1, 0b000); } - static inline int RES_IY_2_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 2, 0b000); } - static inline int RES_IY_3_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 3, 0b000); } - static inline int RES_IY_4_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 4, 0b000); } - static inline int RES_IY_5_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 5, 0b000); } - static inline int RES_IY_6_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 6, 0b000); } - static inline int RES_IY_7_with_LD_B(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 7, 0b000); } - static inline int RES_IY_0_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 0, 0b001); } - static inline int RES_IY_1_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 1, 0b001); } - static inline int RES_IY_2_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 2, 0b001); } - static inline int RES_IY_3_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 3, 0b001); } - static inline int RES_IY_4_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 4, 0b001); } - static inline int RES_IY_5_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 5, 0b001); } - static inline int RES_IY_6_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 6, 0b001); } - static inline int RES_IY_7_with_LD_C(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 7, 0b001); } - static inline int RES_IY_0_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 0, 0b010); } - static inline int RES_IY_1_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 1, 0b010); } - static inline int RES_IY_2_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 2, 0b010); } - static inline int RES_IY_3_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 3, 0b010); } - static inline int RES_IY_4_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 4, 0b010); } - static inline int RES_IY_5_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 5, 0b010); } - static inline int RES_IY_6_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 6, 0b010); } - static inline int RES_IY_7_with_LD_D(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 7, 0b010); } - static inline int RES_IY_0_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 0, 0b011); } - static inline int RES_IY_1_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 1, 0b011); } - static inline int RES_IY_2_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 2, 0b011); } - static inline int RES_IY_3_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 3, 0b011); } - static inline int RES_IY_4_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 4, 0b011); } - static inline int RES_IY_5_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 5, 0b011); } - static inline int RES_IY_6_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 6, 0b011); } - static inline int RES_IY_7_with_LD_E(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 7, 0b011); } - static inline int RES_IY_0_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 0, 0b100); } - static inline int RES_IY_1_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 1, 0b100); } - static inline int RES_IY_2_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 2, 0b100); } - static inline int RES_IY_3_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 3, 0b100); } - static inline int RES_IY_4_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 4, 0b100); } - static inline int RES_IY_5_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 5, 0b100); } - static inline int RES_IY_6_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 6, 0b100); } - static inline int RES_IY_7_with_LD_H(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 7, 0b100); } - static inline int RES_IY_0_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 0, 0b101); } - static inline int RES_IY_1_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 1, 0b101); } - static inline int RES_IY_2_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 2, 0b101); } - static inline int RES_IY_3_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 3, 0b101); } - static inline int RES_IY_4_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 4, 0b101); } - static inline int RES_IY_5_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 5, 0b101); } - static inline int RES_IY_6_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 6, 0b101); } - static inline int RES_IY_7_with_LD_L(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 7, 0b101); } - static inline int RES_IY_0_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 0, 0b111); } - static inline int RES_IY_1_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 1, 0b111); } - static inline int RES_IY_2_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 2, 0b111); } - static inline int RES_IY_3_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 3, 0b111); } - static inline int RES_IY_4_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 4, 0b111); } - static inline int RES_IY_5_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 5, 0b111); } - static inline int RES_IY_6_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 6, 0b111); } - static inline int RES_IY_7_with_LD_A(Z80* ctx, signed char d) { return ctx->RES_IY_with_LD(d, 7, 0b111); } - inline int RES_IY_with_LD(signed char d, unsigned char bit, unsigned char r) + RES_IX(d, bit, rp, buf); + } + + // RESET bit b of location (IY+d) with load Reg. + static inline void RES_IY_0_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 0, 0b000); } + static inline void RES_IY_1_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 1, 0b000); } + static inline void RES_IY_2_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 2, 0b000); } + static inline void RES_IY_3_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 3, 0b000); } + static inline void RES_IY_4_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 4, 0b000); } + static inline void RES_IY_5_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 5, 0b000); } + static inline void RES_IY_6_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 6, 0b000); } + static inline void RES_IY_7_with_LD_B(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 7, 0b000); } + static inline void RES_IY_0_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 0, 0b001); } + static inline void RES_IY_1_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 1, 0b001); } + static inline void RES_IY_2_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 2, 0b001); } + static inline void RES_IY_3_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 3, 0b001); } + static inline void RES_IY_4_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 4, 0b001); } + static inline void RES_IY_5_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 5, 0b001); } + static inline void RES_IY_6_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 6, 0b001); } + static inline void RES_IY_7_with_LD_C(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 7, 0b001); } + static inline void RES_IY_0_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 0, 0b010); } + static inline void RES_IY_1_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 1, 0b010); } + static inline void RES_IY_2_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 2, 0b010); } + static inline void RES_IY_3_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 3, 0b010); } + static inline void RES_IY_4_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 4, 0b010); } + static inline void RES_IY_5_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 5, 0b010); } + static inline void RES_IY_6_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 6, 0b010); } + static inline void RES_IY_7_with_LD_D(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 7, 0b010); } + static inline void RES_IY_0_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 0, 0b011); } + static inline void RES_IY_1_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 1, 0b011); } + static inline void RES_IY_2_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 2, 0b011); } + static inline void RES_IY_3_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 3, 0b011); } + static inline void RES_IY_4_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 4, 0b011); } + static inline void RES_IY_5_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 5, 0b011); } + static inline void RES_IY_6_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 6, 0b011); } + static inline void RES_IY_7_with_LD_E(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 7, 0b011); } + static inline void RES_IY_0_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 0, 0b100); } + static inline void RES_IY_1_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 1, 0b100); } + static inline void RES_IY_2_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 2, 0b100); } + static inline void RES_IY_3_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 3, 0b100); } + static inline void RES_IY_4_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 4, 0b100); } + static inline void RES_IY_5_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 5, 0b100); } + static inline void RES_IY_6_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 6, 0b100); } + static inline void RES_IY_7_with_LD_H(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 7, 0b100); } + static inline void RES_IY_0_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 0, 0b101); } + static inline void RES_IY_1_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 1, 0b101); } + static inline void RES_IY_2_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 2, 0b101); } + static inline void RES_IY_3_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 3, 0b101); } + static inline void RES_IY_4_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 4, 0b101); } + static inline void RES_IY_5_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 5, 0b101); } + static inline void RES_IY_6_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 6, 0b101); } + static inline void RES_IY_7_with_LD_L(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 7, 0b101); } + static inline void RES_IY_0_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 0, 0b111); } + static inline void RES_IY_1_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 1, 0b111); } + static inline void RES_IY_2_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 2, 0b111); } + static inline void RES_IY_3_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 3, 0b111); } + static inline void RES_IY_4_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 4, 0b111); } + static inline void RES_IY_5_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 5, 0b111); } + static inline void RES_IY_6_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 6, 0b111); } + static inline void RES_IY_7_with_LD_A(Z80* ctx, signed char d) { ctx->RES_IY_with_LD(d, 7, 0b111); } + inline void RES_IY_with_LD(signed char d, unsigned char bit, unsigned char r) { char buf[80]; unsigned char* rp = getRegisterPointer(r); @@ -4872,23 +4443,23 @@ class Z80 } else { buf[0] = '\0'; } - return RES_IY(d, bit, rp, buf); + RES_IY(d, bit, rp, buf); } - // RESET bit b of lacation (IY+d) - static inline int RES_IY_0(Z80* ctx, signed char d) { return ctx->RES_IY(d, 0); } - static inline int RES_IY_1(Z80* ctx, signed char d) { return ctx->RES_IY(d, 1); } - static inline int RES_IY_2(Z80* ctx, signed char d) { return ctx->RES_IY(d, 2); } - static inline int RES_IY_3(Z80* ctx, signed char d) { return ctx->RES_IY(d, 3); } - static inline int RES_IY_4(Z80* ctx, signed char d) { return ctx->RES_IY(d, 4); } - static inline int RES_IY_5(Z80* ctx, signed char d) { return ctx->RES_IY(d, 5); } - static inline int RES_IY_6(Z80* ctx, signed char d) { return ctx->RES_IY(d, 6); } - static inline int RES_IY_7(Z80* ctx, signed char d) { return ctx->RES_IY(d, 7); } - inline int RES_IY(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) + // RESET bit b of location (IY+d) + static inline void RES_IY_0(Z80* ctx, signed char d) { ctx->RES_IY(d, 0); } + static inline void RES_IY_1(Z80* ctx, signed char d) { ctx->RES_IY(d, 1); } + static inline void RES_IY_2(Z80* ctx, signed char d) { ctx->RES_IY(d, 2); } + static inline void RES_IY_3(Z80* ctx, signed char d) { ctx->RES_IY(d, 3); } + static inline void RES_IY_4(Z80* ctx, signed char d) { ctx->RES_IY(d, 4); } + static inline void RES_IY_5(Z80* ctx, signed char d) { ctx->RES_IY(d, 5); } + static inline void RES_IY_6(Z80* ctx, signed char d) { ctx->RES_IY(d, 6); } + static inline void RES_IY_7(Z80* ctx, signed char d) { ctx->RES_IY(d, 7); } + inline void RES_IY(signed char d, unsigned char bit, unsigned char* rp = nullptr, const char* extraLog = nullptr) { unsigned short addr = (unsigned short)(reg.IY + d); unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] RES (IY+d<$%04X>) = $%02X of bit-%d%s", reg.PC, addr, n, bit, extraLog ? extraLog : ""); + if (isDebug()) log("[%04X] RES (IY+d<$%04X>) = $%02X of bit-%d%s", reg.PC - 4, addr, n, bit, extraLog ? extraLog : ""); switch (bit) { case 0: n &= 0b11111110; break; case 1: n &= 0b11111101; break; @@ -4901,21 +4472,19 @@ class Z80 } if (rp) *rp = n; writeByte(addr, n, 3); - reg.PC += 4; - return 0; } // Compare location (HL) and A, increment/decrement HL and decrement BC - inline int repeatCP(bool isIncHL, bool isRepeat) + inline void repeatCP(bool isIncHL, bool isRepeat) { unsigned short hl = getHL(); unsigned short bc = getBC(); unsigned char n = readByte(hl); if (isDebug()) { if (isIncHL) { - log("[%04X] %s ... %s, %s = $%02X, %s", reg.PC, isRepeat ? "CPIR" : "CPI", registerDump(0b111), registerPairDump(0b10), n, registerPairDump(0b00)); + log("[%04X] %s ... %s, %s = $%02X, %s", reg.PC - 2, isRepeat ? "CPIR" : "CPI", registerDump(0b111), registerPairDump(0b10), n, registerPairDump(0b00)); } else { - log("[%04X] %s ... %s, %s = $%02X, %s", reg.PC, isRepeat ? "CPDR" : "CPD", registerDump(0b111), registerPairDump(0b10), n, registerPairDump(0b00)); + log("[%04X] %s ... %s, %s = $%02X, %s", reg.PC - 2, isRepeat ? "CPDR" : "CPD", registerDump(0b111), registerPairDump(0b10), n, registerPairDump(0b00)); } } subtract8(n, 0, false, false); @@ -4930,422 +4499,293 @@ class Z80 setFlagPV(0 != bc); consumeClock(4); if (isRepeat && !isFlagZ() && 0 != getBC()) { + reg.PC -= 2; consumeClock(5); - } else { - reg.PC += 2; } reg.WZ += isIncHL ? 1 : -1; - return 0; } - static inline int CPI(Z80* ctx) { return ctx->repeatCP(true, false); } - static inline int CPIR(Z80* ctx) { return ctx->repeatCP(true, true); } - static inline int CPD(Z80* ctx) { return ctx->repeatCP(false, false); } - static inline int CPDR(Z80* ctx) { return ctx->repeatCP(false, true); } + static inline void CPI(Z80* ctx) { ctx->repeatCP(true, false); } + static inline void CPIR(Z80* ctx) { ctx->repeatCP(true, true); } + static inline void CPD(Z80* ctx) { ctx->repeatCP(false, false); } + static inline void CPDR(Z80* ctx) { ctx->repeatCP(false, true); } // Compare Register - static inline int CP_B(Z80* ctx) { return ctx->CP_R(0b000); } - static inline int CP_C(Z80* ctx) { return ctx->CP_R(0b001); } - static inline int CP_D(Z80* ctx) { return ctx->CP_R(0b010); } - static inline int CP_E(Z80* ctx) { return ctx->CP_R(0b011); } - static inline int CP_H(Z80* ctx) { return ctx->CP_R(0b100); } - static inline int CP_L(Z80* ctx) { return ctx->CP_R(0b101); } - static inline int CP_A(Z80* ctx) { return ctx->CP_R(0b111); } - static inline int CP_B_2(Z80* ctx) { return ctx->CP_R(0b000, 2); } - static inline int CP_C_2(Z80* ctx) { return ctx->CP_R(0b001, 2); } - static inline int CP_D_2(Z80* ctx) { return ctx->CP_R(0b010, 2); } - static inline int CP_E_2(Z80* ctx) { return ctx->CP_R(0b011, 2); } - static inline int CP_A_2(Z80* ctx) { return ctx->CP_R(0b111, 2); } - inline int CP_R(unsigned char r, int pc = 1) - { - if (isDebug()) log("[%04X] CP %s, %s", reg.PC, registerDump(0b111), registerDump(r)); + static inline void CP_B(Z80* ctx) { ctx->CP_R(0b000); } + static inline void CP_C(Z80* ctx) { ctx->CP_R(0b001); } + static inline void CP_D(Z80* ctx) { ctx->CP_R(0b010); } + static inline void CP_E(Z80* ctx) { ctx->CP_R(0b011); } + static inline void CP_H(Z80* ctx) { ctx->CP_R(0b100); } + static inline void CP_L(Z80* ctx) { ctx->CP_R(0b101); } + static inline void CP_A(Z80* ctx) { ctx->CP_R(0b111); } + static inline void CP_B_2(Z80* ctx) { ctx->CP_R(0b000, 2); } + static inline void CP_C_2(Z80* ctx) { ctx->CP_R(0b001, 2); } + static inline void CP_D_2(Z80* ctx) { ctx->CP_R(0b010, 2); } + static inline void CP_E_2(Z80* ctx) { ctx->CP_R(0b011, 2); } + static inline void CP_A_2(Z80* ctx) { ctx->CP_R(0b111, 2); } + inline void CP_R(unsigned char r, int pc = 1) + { + if (isDebug()) log("[%04X] CP %s, %s", reg.PC - pc, registerDump(0b111), registerDump(r)); unsigned char* rp = getRegisterPointer(r); subtract8(*rp, 0, true, false); - reg.PC += pc; - return 0; } // Compare Register IXH - static inline int CP_IXH_(Z80* ctx) { return ctx->CP_IXH(); } - inline int CP_IXH() + static inline void CP_IXH_(Z80* ctx) { ctx->CP_IXH(); } + inline void CP_IXH() { - if (isDebug()) log("[%04X] CP %s, IXH<$%02X>", reg.PC, registerDump(0b111), getIXH()); + if (isDebug()) log("[%04X] CP %s, IXH<$%02X>", reg.PC - 2, registerDump(0b111), getIXH()); subtract8(getIXH(), 0, true, false); - reg.PC += 2; - return 0; } // Compare Register IXL - static inline int CP_IXL_(Z80* ctx) { return ctx->CP_IXL(); } - inline int CP_IXL() + static inline void CP_IXL_(Z80* ctx) { ctx->CP_IXL(); } + inline void CP_IXL() { - if (isDebug()) log("[%04X] CP %s, IXL<$%02X>", reg.PC, registerDump(0b111), getIXL()); + if (isDebug()) log("[%04X] CP %s, IXL<$%02X>", reg.PC - 2, registerDump(0b111), getIXL()); subtract8(getIXL(), 0, true, false); - reg.PC += 2; - return 0; } // Compare Register IYH - static inline int CP_IYH_(Z80* ctx) { return ctx->CP_IYH(); } - inline int CP_IYH() + static inline void CP_IYH_(Z80* ctx) { ctx->CP_IYH(); } + inline void CP_IYH() { - if (isDebug()) log("[%04X] CP %s, IYH<$%02X>", reg.PC, registerDump(0b111), getIYH()); + if (isDebug()) log("[%04X] CP %s, IYH<$%02X>", reg.PC - 2, registerDump(0b111), getIYH()); subtract8(getIYH(), 0, true, false); - reg.PC += 2; - return 0; } // Compare Register IYL - static inline int CP_IYL_(Z80* ctx) { return ctx->CP_IYL(); } - inline int CP_IYL() + static inline void CP_IYL_(Z80* ctx) { ctx->CP_IYL(); } + inline void CP_IYL() { - if (isDebug()) log("[%04X] CP %s, IYL<$%02X>", reg.PC, registerDump(0b111), getIYL()); + if (isDebug()) log("[%04X] CP %s, IYL<$%02X>", reg.PC - 2, registerDump(0b111), getIYL()); subtract8(getIYL(), 0, true, false); - reg.PC += 2; - return 0; } // Compare immediate - static inline int CP_N(Z80* ctx) + static inline void CP_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] CP %s, $%02X", ctx->reg.PC, ctx->registerDump(0b111), n); + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] CP %s, $%02X", ctx->reg.PC - 2, ctx->registerDump(0b111), n); ctx->subtract8(n, 0, true, false); - ctx->reg.PC += 2; - return 0; } // Compare memory - static inline int CP_HL(Z80* ctx) + static inline void CP_HL(Z80* ctx) { - unsigned short addr = ctx->getHL(); - unsigned char n = ctx->readByte(addr, 3); - if (ctx->isDebug()) ctx->log("[%04X] CP %s, (%s) = $%02X", ctx->reg.PC, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); + unsigned char n = ctx->readByte(ctx->getHL(), 3); + if (ctx->isDebug()) ctx->log("[%04X] CP %s, (%s) = $%02X", ctx->reg.PC - 1, ctx->registerDump(0b111), ctx->registerPairDump(0b10), n); ctx->subtract8(n, 0, true, false); - ctx->reg.PC += 1; - return 0; } // Compare memory - static inline int CP_IX_(Z80* ctx) { return ctx->CP_IX(); } - inline int CP_IX() + static inline void CP_IX_(Z80* ctx) { ctx->CP_IX(); } + inline void CP_IX() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IX + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] CP %s, (IX+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, n); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IX + d)); + if (isDebug()) log("[%04X] CP %s, (IX+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IX + d), n); subtract8(n, 0, true, false); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Compare memory - static inline int CP_IY_(Z80* ctx) { return ctx->CP_IY(); } - inline int CP_IY() + static inline void CP_IY_(Z80* ctx) { ctx->CP_IY(); } + inline void CP_IY() { - signed char d = (signed char)readByte(reg.PC + 2); - unsigned short addr = (unsigned short)(reg.IY + d); - unsigned char n = readByte(addr); - if (isDebug()) log("[%04X] CP %s, (IY+d<$%04X>) = $%02X", reg.PC, registerDump(0b111), addr, n); + signed char d = (signed char)fetch(4); + unsigned char n = readByte((unsigned short)(reg.IY + d)); + if (isDebug()) log("[%04X] CP %s, (IY+d<$%04X>) = $%02X", reg.PC - 3, registerDump(0b111), (unsigned short)(reg.IY + d), n); subtract8(n, 0, true, false); - reg.PC += 3; - return consumeClock(3); + consumeClock(3); } // Jump - static inline int JP_NN(Z80* ctx) + static inline void JP_NN(Z80* ctx) { - unsigned char nL = ctx->readByte(ctx->reg.PC + 1, 3); - unsigned char nH = ctx->readByte(ctx->reg.PC + 2, 3); - unsigned short addr = (nH << 8) + nL; - if (ctx->isDebug()) ctx->log("[%04X] JP $%04X", ctx->reg.PC, addr); + unsigned char l = ctx->fetch(3); + unsigned char h = ctx->fetch(3); + unsigned short addr = ctx->make16BitsFromLE(l, h); + if (ctx->isDebug()) ctx->log("[%04X] JP $%04X", ctx->reg.PC - 3, addr); ctx->reg.PC = addr; ctx->reg.WZ = addr; - return 0; } // Conditional Jump - static inline int JP_C0_NN(Z80* ctx) { return ctx->JP_C_NN(0); } - static inline int JP_C1_NN(Z80* ctx) { return ctx->JP_C_NN(1); } - static inline int JP_C2_NN(Z80* ctx) { return ctx->JP_C_NN(2); } - static inline int JP_C3_NN(Z80* ctx) { return ctx->JP_C_NN(3); } - static inline int JP_C4_NN(Z80* ctx) { return ctx->JP_C_NN(4); } - static inline int JP_C5_NN(Z80* ctx) { return ctx->JP_C_NN(5); } - static inline int JP_C6_NN(Z80* ctx) { return ctx->JP_C_NN(6); } - static inline int JP_C7_NN(Z80* ctx) { return ctx->JP_C_NN(7); } - inline int JP_C_NN(unsigned char c) - { - unsigned char nL = readByte(reg.PC + 1, 3); - unsigned char nH = readByte(reg.PC + 2, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] JP %s, $%04X", reg.PC, conditionDump(c), addr); - bool jump; - switch (c) { - case 0: jump = isFlagZ() ? false : true; break; - case 1: jump = isFlagZ() ? true : false; break; - case 2: jump = isFlagC() ? false : true; break; - case 3: jump = isFlagC() ? true : false; break; - case 4: jump = isFlagPV() ? false : true; break; - case 5: jump = isFlagPV() ? true : false; break; - case 6: jump = isFlagS() ? false : true; break; - case 7: jump = isFlagS() ? true : false; break; - default: jump = false; - } - if (jump) { - reg.PC = addr; - } else { - reg.PC += 3; - } + static inline void JP_C0_NN(Z80* ctx) { ctx->JP_C_NN(0); } + static inline void JP_C1_NN(Z80* ctx) { ctx->JP_C_NN(1); } + static inline void JP_C2_NN(Z80* ctx) { ctx->JP_C_NN(2); } + static inline void JP_C3_NN(Z80* ctx) { ctx->JP_C_NN(3); } + static inline void JP_C4_NN(Z80* ctx) { ctx->JP_C_NN(4); } + static inline void JP_C5_NN(Z80* ctx) { ctx->JP_C_NN(5); } + static inline void JP_C6_NN(Z80* ctx) { ctx->JP_C_NN(6); } + static inline void JP_C7_NN(Z80* ctx) { ctx->JP_C_NN(7); } + inline void JP_C_NN(unsigned char c) + { + unsigned char l = fetch(3); + unsigned char h = fetch(3); + unsigned short addr = make16BitsFromLE(l, h); + if (isDebug()) log("[%04X] JP %s, $%04X", reg.PC - 3, conditionDump(c), addr); + if (checkConditionFlag(c)) reg.PC = addr; reg.WZ = addr; - return 0; } // Jump Relative to PC+e - static inline int JR_E(Z80* ctx) + static inline void JR_E(Z80* ctx) { - signed char e = (signed char)ctx->readByte(ctx->reg.PC + 1); - if (ctx->isDebug()) ctx->log("[%04X] JR %s", ctx->reg.PC, ctx->relativeDump(e)); + signed char e = (signed char)ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] JR %s", ctx->reg.PC - 2, ctx->relativeDump(ctx->reg.PC - 2, e)); ctx->reg.PC += e; - ctx->reg.PC += 2; - return ctx->consumeClock(4); - } - - // Jump Relative to PC+e, if carry - static inline int JR_C_E(Z80* ctx) - { - signed char e = (signed char)ctx->readByte(ctx->reg.PC + 1, 3); - bool execute = ctx->isFlagC(); - if (ctx->isDebug()) ctx->log("[%04X] JR C, %s <%s>", ctx->reg.PC, ctx->relativeDump(e), execute ? "YES" : "NO"); - ctx->reg.PC += 2; - if (execute) { - ctx->reg.PC += e; - ctx->consumeClock(5); - } - return 0; - } - - // Jump Relative to PC+e, if not carry - static inline int JR_NC_E(Z80* ctx) - { - signed char e = (signed char)ctx->readByte(ctx->reg.PC + 1, 3); - bool execute = !ctx->isFlagC(); - if (ctx->isDebug()) ctx->log("[%04X] JR NC, %s <%s>", ctx->reg.PC, ctx->relativeDump(e), execute ? "YES" : "NO"); - ctx->reg.PC += 2; - if (execute) { - ctx->reg.PC += e; - ctx->consumeClock(5); - } - return 0; - } - - // Jump Relative to PC+e, if zero - static inline int JR_Z_E(Z80* ctx) - { - signed char e = (signed char)ctx->readByte(ctx->reg.PC + 1, 3); - bool execute = ctx->isFlagZ(); - if (ctx->isDebug()) ctx->log("[%04X] JR Z, %s <%s>", ctx->reg.PC, ctx->relativeDump(e), execute ? "YES" : "NO"); - ctx->reg.PC += 2; - if (execute) { - ctx->reg.PC += e; - ctx->consumeClock(5); - } - return 0; + ctx->consumeClock(5); } - // Jump Relative to PC+e, if zero - static inline int JR_NZ_E(Z80* ctx) + // Jump Relative to PC+e, if condition + static inline void JR_NZ_E(Z80* ctx) { ctx->JR_CND_E(0); } + static inline void JR_Z_E(Z80* ctx) { ctx->JR_CND_E(1); } + static inline void JR_NC_E(Z80* ctx) { ctx->JR_CND_E(2); } + static inline void JR_C_E(Z80* ctx) { ctx->JR_CND_E(3); } + inline void JR_CND_E(unsigned char cnd) { - signed char e = (signed char)ctx->readByte(ctx->reg.PC + 1, 3); - bool execute = !ctx->isFlagZ(); - if (ctx->isDebug()) ctx->log("[%04X] JR NZ, %s <%s>", ctx->reg.PC, ctx->relativeDump(e), execute ? "YES" : "NO"); - ctx->reg.PC += 2; - if (execute) { - ctx->reg.PC += e; - ctx->consumeClock(5); + signed char e = (signed char)fetch(3); + if (isDebug()) log("[%04X] JR %s, %s <%s>", reg.PC - 2, conditionDump(cnd), relativeDump(reg.PC - 2, e), checkConditionFlag(cnd) ? "YES" : "NO"); + if (checkConditionFlag(cnd)) { + reg.PC += e; + consumeClock(5); } - return 0; } // Jump to HL - static inline int JP_HL(Z80* ctx) + static inline void JP_HL(Z80* ctx) { - if (ctx->isDebug()) ctx->log("[%04X] JP %s", ctx->reg.PC, ctx->registerPairDump(0b10)); + if (ctx->isDebug()) ctx->log("[%04X] JP %s", ctx->reg.PC - 1, ctx->registerPairDump(0b10)); ctx->reg.PC = ctx->getHL(); - return 0; } // Jump to IX - static inline int JP_IX_(Z80* ctx) { return ctx->JP_IX(); } - inline int JP_IX() + static inline void JP_IX(Z80* ctx) { - if (isDebug()) log("[%04X] JP IX<$%04X>", reg.PC, reg.IX); - reg.PC = reg.IX; - return 0; + if (ctx->isDebug()) ctx->log("[%04X] JP IX<$%04X>", ctx->reg.PC - 2, ctx->reg.IX); + ctx->reg.PC = ctx->reg.IX; } // Jump to IY - static inline int JP_IY_(Z80* ctx) { return ctx->JP_IY(); } - inline int JP_IY() + static inline void JP_IY(Z80* ctx) { - if (isDebug()) log("[%04X] JP IY<$%04X>", reg.PC, reg.IY); - reg.PC = reg.IY; - return 0; + if (ctx->isDebug()) ctx->log("[%04X] JP IY<$%04X>", ctx->reg.PC - 2, ctx->reg.IY); + ctx->reg.PC = ctx->reg.IY; } // Decrement B and Jump relative if B=0 - static inline int DJNZ_E(Z80* ctx) + static inline void DJNZ_E(Z80* ctx) { - signed char e = (signed char)ctx->readByte(ctx->reg.PC + 1); - if (ctx->isDebug()) ctx->log("[%04X] DJNZ %s (%s)", ctx->reg.PC, ctx->relativeDump(e), ctx->registerDump(0b000)); + signed char e = (signed char)ctx->fetch(4); + if (ctx->isDebug()) ctx->log("[%04X] DJNZ %s (%s)", ctx->reg.PC - 2, ctx->relativeDump(ctx->reg.PC - 2, e), ctx->registerDump(0b000)); ctx->reg.pair.B--; - ctx->reg.PC += 2; if (ctx->reg.pair.B) { ctx->reg.PC += e; ctx->consumeClock(5); } - return 0; } // Call - static inline int CALL_NN(Z80* ctx) - { - unsigned char nL = ctx->readByte(ctx->reg.PC + 1); - unsigned char nH = ctx->readByte(ctx->reg.PC + 2, 3); - unsigned short addr = (nH << 8) + nL; - if (ctx->isDebug()) ctx->log("[%04X] CALL $%04X (%s)", ctx->reg.PC, addr, ctx->registerPairDump(0b11)); - ctx->reg.PC += 3; - unsigned char pcL = ctx->reg.PC & 0x00FF; - unsigned char pcH = (ctx->reg.PC & 0xFF00) >> 8; - ctx->writeByte(ctx->reg.SP - 1, pcH, 3); - ctx->writeByte(ctx->reg.SP - 2, pcL, 3); - ctx->reg.SP -= 2; - ctx->reg.WZ = addr; - ctx->reg.PC = addr; + static inline void CALL_NN(Z80* ctx) + { + unsigned short addrL = ctx->fetch(4); + unsigned short addrH = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] CALL $%04X (%s)", ctx->reg.PC - 3, ctx->make16BitsFromLE(addrL, addrH), ctx->registerPairDump(0b11)); + ctx->push(ctx->getPCH(), 3); + ctx->setPCH(addrH); + ctx->push(ctx->getPCL(), 3); + ctx->setPCL(addrL); + ctx->reg.WZ = ctx->reg.PC; ctx->invokeCallHandlers(); - return 0; } // Return - static inline int RET(Z80* ctx) + static inline void RET(Z80* ctx) { ctx->invokeReturnHandlers(); - unsigned char nL = ctx->readByte(ctx->reg.SP, 3); - unsigned char nH = ctx->readByte(ctx->reg.SP + 1, 3); - unsigned short addr = (nH << 8) + nL; - if (ctx->isDebug()) ctx->log("[%04X] RET to $%04X (%s)", ctx->reg.PC, addr, ctx->registerPairDump(0b11)); - ctx->reg.SP += 2; - ctx->reg.PC = addr; - ctx->reg.WZ = addr; - return 0; + unsigned short pc = ctx->reg.PC - 1; + const char* dump = ctx->isDebug() ? ctx->registerPairDump(0b11) : ""; + ctx->setPCL(ctx->pop(3)); + ctx->setPCH(ctx->pop(3)); + ctx->reg.WZ = ctx->reg.PC; + if (ctx->isDebug()) ctx->log("[%04X] RET to $%04X (%s)", pc, ctx->reg.PC, dump); } // Call with condition - static inline int CALL_C0_NN(Z80* ctx) { return ctx->CALL_C_NN(0); } - static inline int CALL_C1_NN(Z80* ctx) { return ctx->CALL_C_NN(1); } - static inline int CALL_C2_NN(Z80* ctx) { return ctx->CALL_C_NN(2); } - static inline int CALL_C3_NN(Z80* ctx) { return ctx->CALL_C_NN(3); } - static inline int CALL_C4_NN(Z80* ctx) { return ctx->CALL_C_NN(4); } - static inline int CALL_C5_NN(Z80* ctx) { return ctx->CALL_C_NN(5); } - static inline int CALL_C6_NN(Z80* ctx) { return ctx->CALL_C_NN(6); } - static inline int CALL_C7_NN(Z80* ctx) { return ctx->CALL_C_NN(7); } - inline int CALL_C_NN(unsigned char c) - { - bool execute; - switch (c) { - case 0b000: execute = isFlagZ() ? false : true; break; - case 0b001: execute = isFlagZ() ? true : false; break; - case 0b010: execute = isFlagC() ? false : true; break; - case 0b011: execute = isFlagC() ? true : false; break; - case 0b100: execute = isFlagPV() ? false : true; break; - case 0b101: execute = isFlagPV() ? true : false; break; - case 0b110: execute = isFlagS() ? false : true; break; - case 0b111: execute = isFlagS() ? true : false; break; - default: execute = false; - } - unsigned char nL = readByte(reg.PC + 1, 3); - unsigned char nH = readByte(reg.PC + 2, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] CALL %s, $%04X (%s) ", reg.PC, conditionDump(c), addr, registerPairDump(0b11), execute ? "YES" : "NO"); - reg.PC += 3; + static inline void CALL_C0_NN(Z80* ctx) { ctx->CALL_C_NN(0); } + static inline void CALL_C1_NN(Z80* ctx) { ctx->CALL_C_NN(1); } + static inline void CALL_C2_NN(Z80* ctx) { ctx->CALL_C_NN(2); } + static inline void CALL_C3_NN(Z80* ctx) { ctx->CALL_C_NN(3); } + static inline void CALL_C4_NN(Z80* ctx) { ctx->CALL_C_NN(4); } + static inline void CALL_C5_NN(Z80* ctx) { ctx->CALL_C_NN(5); } + static inline void CALL_C6_NN(Z80* ctx) { ctx->CALL_C_NN(6); } + static inline void CALL_C7_NN(Z80* ctx) { ctx->CALL_C_NN(7); } + inline void CALL_C_NN(unsigned char c) + { + bool execute = checkConditionFlag(c); + unsigned char nL = fetch(3); + unsigned char nH = fetch(3); + if (isDebug()) log("[%04X] CALL %s, $%04X (%s) ", reg.PC - 3, conditionDump(c), make16BitsFromLE(nL, nH), registerPairDump(0b11), execute ? "YES" : "NO"); if (execute) { - unsigned char pcL = reg.PC & 0x00FF; - unsigned char pcH = (reg.PC & 0xFF00) >> 8; - writeByte(reg.SP - 1, pcH); - writeByte(reg.SP - 2, pcL, 3); - reg.SP -= 2; - reg.PC = addr; + push(getPCH(), 4); + setPCH(nH); + push(getPCL(), 3); + setPCL(nL); invokeCallHandlers(); } - reg.WZ = addr; - return 0; - } - - // Return with condition - static inline int RET_C0(Z80* ctx) { return ctx->RET_C(0); } - static inline int RET_C1(Z80* ctx) { return ctx->RET_C(1); } - static inline int RET_C2(Z80* ctx) { return ctx->RET_C(2); } - static inline int RET_C3(Z80* ctx) { return ctx->RET_C(3); } - static inline int RET_C4(Z80* ctx) { return ctx->RET_C(4); } - static inline int RET_C5(Z80* ctx) { return ctx->RET_C(5); } - static inline int RET_C6(Z80* ctx) { return ctx->RET_C(6); } - static inline int RET_C7(Z80* ctx) { return ctx->RET_C(7); } - inline int RET_C(unsigned char c) - { - bool execute; - switch (c) { - case 0: execute = isFlagZ() ? false : true; break; - case 1: execute = isFlagZ() ? true : false; break; - case 2: execute = isFlagC() ? false : true; break; - case 3: execute = isFlagC() ? true : false; break; - case 4: execute = isFlagPV() ? false : true; break; - case 5: execute = isFlagPV() ? true : false; break; - case 6: execute = isFlagS() ? false : true; break; - case 7: execute = isFlagS() ? true : false; break; - default: execute = false; - } - if (!execute) { - if (isDebug()) log("[%04X] RET %s ", reg.PC, conditionDump(c)); - reg.PC++; - return consumeClock(1); + reg.WZ = reg.PC; + } + + // with condition + static inline void RET_C0(Z80* ctx) { ctx->RET_C(0); } + static inline void RET_C1(Z80* ctx) { ctx->RET_C(1); } + static inline void RET_C2(Z80* ctx) { ctx->RET_C(2); } + static inline void RET_C3(Z80* ctx) { ctx->RET_C(3); } + static inline void RET_C4(Z80* ctx) { ctx->RET_C(4); } + static inline void RET_C5(Z80* ctx) { ctx->RET_C(5); } + static inline void RET_C6(Z80* ctx) { ctx->RET_C(6); } + static inline void RET_C7(Z80* ctx) { ctx->RET_C(7); } + inline void RET_C(unsigned char c) + { + if (!checkConditionFlag(c)) { + if (isDebug()) log("[%04X] RET %s ", reg.PC - 1, conditionDump(c)); + consumeClock(1); + return; } invokeReturnHandlers(); - unsigned char nL = readByte(reg.SP); - unsigned char nH = readByte(reg.SP + 1, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] RET %s to $%04X (%s) ", reg.PC, conditionDump(c), addr, registerPairDump(0b11)); - reg.SP += 2; - reg.PC = addr; - reg.WZ = addr; - return 0; + unsigned short pc = reg.PC; + unsigned short sp = reg.SP; + setPCL(pop(4)); + setPCH(pop(3)); + reg.WZ = reg.PC; + if (isDebug()) log("[%04X] RET %s to $%04X (SP<$%04X>) ", pc - 1, conditionDump(c), reg.PC, sp); } // Return from interrupt - static inline int RETI_(Z80* ctx) { return ctx->RETI(); } - inline int RETI() + static inline void RETI_(Z80* ctx) { ctx->RETI(); } + inline void RETI() { invokeReturnHandlers(); - unsigned char nL = readByte(reg.SP, 3); - unsigned char nH = readByte(reg.SP + 1, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] RETI to $%04X (%s)", reg.PC, addr, registerPairDump(0b11)); - reg.SP += 2; - reg.PC = addr; - reg.WZ = addr; + unsigned short pc = reg.PC; + unsigned short sp = reg.SP; + setPCL(pop(3)); + setPCH(pop(3)); + reg.WZ = reg.PC; reg.IFF &= ~IFF_IRQ(); - return 0; + if (isDebug()) log("[%04X] RETI to $%04X (SP<$%04X>)", pc - 2, reg.PC, sp); } // Return from non maskable interrupt - static inline int RETN_(Z80* ctx) { return ctx->RETN(); } - inline int RETN() + static inline void RETN_(Z80* ctx) { ctx->RETN(); } + inline void RETN() { invokeReturnHandlers(); - unsigned char nL = readByte(reg.SP, 3); - unsigned char nH = readByte(reg.SP + 1, 3); - unsigned short addr = (nH << 8) + nL; - if (isDebug()) log("[%04X] RETN to $%04X (%s)", reg.PC, addr, registerPairDump(0b11)); - reg.SP += 2; - reg.PC = addr; - reg.WZ = addr; + unsigned short pc = reg.PC; + unsigned short sp = reg.SP; + setPCL(pop(3)); + setPCH(pop(3)); + reg.WZ = reg.PC; reg.IFF &= ~IFF_NMI(); if (!((reg.IFF & IFF1()) && (reg.IFF & IFF2()))) { reg.IFF |= IFF1(); @@ -5356,63 +4796,59 @@ class Z80 reg.IFF &= ~IFF1(); } } - return 0; + if (isDebug()) log("[%04X] RETN to $%04X (SP<$%04X>)", pc - 2, reg.PC, sp); } // Interrupt - static inline int RST00(Z80* ctx) { return ctx->RST(0, true); } - static inline int RST08(Z80* ctx) { return ctx->RST(1, true); } - static inline int RST10(Z80* ctx) { return ctx->RST(2, true); } - static inline int RST18(Z80* ctx) { return ctx->RST(3, true); } - static inline int RST20(Z80* ctx) { return ctx->RST(4, true); } - static inline int RST28(Z80* ctx) { return ctx->RST(5, true); } - static inline int RST30(Z80* ctx) { return ctx->RST(6, true); } - static inline int RST38(Z80* ctx) { return ctx->RST(7, true); } - inline int RST(unsigned char t, bool incrementPC) + static inline void RST00(Z80* ctx) { ctx->RST(0, true); } + static inline void RST08(Z80* ctx) { ctx->RST(1, true); } + static inline void RST10(Z80* ctx) { ctx->RST(2, true); } + static inline void RST18(Z80* ctx) { ctx->RST(3, true); } + static inline void RST20(Z80* ctx) { ctx->RST(4, true); } + static inline void RST28(Z80* ctx) { ctx->RST(5, true); } + static inline void RST30(Z80* ctx) { ctx->RST(6, true); } + static inline void RST38(Z80* ctx) { ctx->RST(7, true); } + inline void RST(unsigned char t, bool isOperand) { unsigned short addr = t * 8; - if (isDebug()) log("[%04X] RST $%04X (%s)", reg.PC, addr, registerPairDump(0b11)); - if (incrementPC) reg.PC++; - unsigned char pcH = (reg.PC & 0xFF00) >> 8; - unsigned char pcL = reg.PC & 0x00FF; - writeByte(reg.SP - 1, pcH); - writeByte(reg.SP - 2, pcL, 3); - reg.SP -= 2; - reg.WZ = addr; + unsigned short sp = reg.SP; + unsigned short pc = reg.PC; + push(getPCH(), 4); + setPCH(0); + push(getPCL(), 3); reg.PC = addr; + reg.WZ = addr; + if (isDebug()) log("[%04X] RST $%04X (SP<$%04X>)", pc - (isOperand ? 1 : 0), addr, sp); invokeCallHandlers(); - return 0; } // Input a byte form device n to accu. - static inline int IN_A_N(Z80* ctx) + static inline void IN_A_N(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); + unsigned char n = ctx->fetch(3); unsigned char i = ctx->inPort(n); - if (ctx->isDebug()) ctx->log("[%04X] IN %s, ($%02X) = $%02X", ctx->reg.PC, ctx->registerDump(0b111), n, i); + if (ctx->isDebug()) ctx->log("[%04X] IN %s, ($%02X) = $%02X", ctx->reg.PC - 2, ctx->registerDump(0b111), n, i); ctx->reg.pair.A = i; - ctx->reg.PC += 2; - return 0; } // Input a byte form device (C) to register. - static inline int IN_B_C(Z80* ctx) { return ctx->IN_R_C(0b000); } - static inline int IN_C_C(Z80* ctx) { return ctx->IN_R_C(0b001); } - static inline int IN_D_C(Z80* ctx) { return ctx->IN_R_C(0b010); } - static inline int IN_E_C(Z80* ctx) { return ctx->IN_R_C(0b011); } - static inline int IN_H_C(Z80* ctx) { return ctx->IN_R_C(0b100); } - static inline int IN_L_C(Z80* ctx) { return ctx->IN_R_C(0b101); } - static inline int IN_C(Z80* ctx) { return ctx->IN_R_C(0, false); } - static inline int IN_A_C(Z80* ctx) { return ctx->IN_R_C(0b111); } - inline int IN_R_C(unsigned char r, bool setRegister = true) + static inline void IN_B_C(Z80* ctx) { ctx->IN_R_C(0b000); } + static inline void IN_C_C(Z80* ctx) { ctx->IN_R_C(0b001); } + static inline void IN_D_C(Z80* ctx) { ctx->IN_R_C(0b010); } + static inline void IN_E_C(Z80* ctx) { ctx->IN_R_C(0b011); } + static inline void IN_H_C(Z80* ctx) { ctx->IN_R_C(0b100); } + static inline void IN_L_C(Z80* ctx) { ctx->IN_R_C(0b101); } + static inline void IN_C(Z80* ctx) { ctx->IN_R_C(0, false); } + static inline void IN_A_C(Z80* ctx) { ctx->IN_R_C(0b111); } + inline void IN_R_C(unsigned char r, bool setRegister = true) { unsigned char* rp = setRegister ? getRegisterPointer(r) : nullptr; unsigned char i = inPort(reg.pair.C); if (rp) { - if (isDebug()) log("[%04X] IN %s, (%s) = $%02X", reg.PC, registerDump(r), registerDump(0b001), i); + if (isDebug()) log("[%04X] IN %s, (%s) = $%02X", reg.PC - 2, registerDump(r), registerDump(0b001), i); *rp = i; } else { - if (isDebug()) log("[%04X] IN (%s) = $%02X", reg.PC, registerDump(0b001), i); + if (isDebug()) log("[%04X] IN (%s) = $%02X", reg.PC - 2, registerDump(0b001), i); } setFlagS(i & 0x80); setFlagZ(i == 0); @@ -5420,8 +4856,6 @@ class Z80 setFlagPV(isEvenNumberBits(i)); setFlagN(false); setFlagXY(i); - reg.PC += 2; - return 0; } inline void decrementB_forRepeatIO() @@ -5438,16 +4872,16 @@ class Z80 } // Load location (HL) with input from port (C); or increment/decrement HL and decrement B - inline int repeatIN(bool isIncHL, bool isRepeat) + inline void repeatIN(bool isIncHL, bool isRepeat) { reg.WZ = (unsigned short)(getBC() + (isIncHL ? 1 : -1)); unsigned char i = inPort(reg.pair.C); unsigned short hl = getHL(); if (isDebug()) { if (isIncHL) { - log("[%04X] %s ... (%s) <- p(%s) = $%02X [%s]", reg.PC, isRepeat ? "INIR" : "INI", registerPairDump(0b10), registerDump(0b001), i, registerDump(0b000)); + log("[%04X] %s ... (%s) <- p(%s) = $%02X [%s]", reg.PC - 2, isRepeat ? "INIR" : "INI", registerPairDump(0b10), registerDump(0b001), i, registerDump(0b000)); } else { - log("[%04X] %s ... (%s) <- p(%s) = $%02X [%s]", reg.PC, isRepeat ? "INDR" : "IND", registerPairDump(0b10), registerDump(0b001), i, registerDump(0b000)); + log("[%04X] %s ... (%s) <- p(%s) = $%02X [%s]", reg.PC - 2, isRepeat ? "INDR" : "IND", registerPairDump(0b10), registerDump(0b001), i, registerDump(0b000)); } } writeByte(hl, i); @@ -5460,86 +4894,76 @@ class Z80 setFlagH(isFlagC()); // NOTE: undocumented setFlagPV((i + (((reg.pair.C + 1) & 0xFF) & 0x07)) ^ reg.pair.B); // NOTE: undocumented if (isRepeat && 0 != reg.pair.B) { + reg.PC -= 2; consumeClock(5); - } else { - reg.PC += 2; } - return 0; } - static inline int INI(Z80* ctx) { return ctx->repeatIN(true, false); } - static inline int INIR(Z80* ctx) { return ctx->repeatIN(true, true); } - static inline int IND(Z80* ctx) { return ctx->repeatIN(false, false); } - static inline int INDR(Z80* ctx) { return ctx->repeatIN(false, true); } + static inline void INI(Z80* ctx) { ctx->repeatIN(true, false); } + static inline void INIR(Z80* ctx) { ctx->repeatIN(true, true); } + static inline void IND(Z80* ctx) { ctx->repeatIN(false, false); } + static inline void INDR(Z80* ctx) { ctx->repeatIN(false, true); } // Load Output port (n) with Acc. - static inline int OUT_N_A(Z80* ctx) + static inline void OUT_N_A(Z80* ctx) { - unsigned char n = ctx->readByte(ctx->reg.PC + 1, 3); - if (ctx->isDebug()) ctx->log("[%04X] OUT ($%02X), %s", ctx->reg.PC, n, ctx->registerDump(0b111)); + unsigned char n = ctx->fetch(3); + if (ctx->isDebug()) ctx->log("[%04X] OUT ($%02X), %s", ctx->reg.PC - 2, n, ctx->registerDump(0b111)); ctx->outPort(n, ctx->reg.pair.A); - ctx->reg.PC += 2; - return 0; } // Output a byte to device (C) form register. - static inline int OUT_C_B(Z80* ctx) { return ctx->OUT_C_R(0b000); } - static inline int OUT_C_C(Z80* ctx) { return ctx->OUT_C_R(0b001); } - static inline int OUT_C_D(Z80* ctx) { return ctx->OUT_C_R(0b010); } - static inline int OUT_C_E(Z80* ctx) { return ctx->OUT_C_R(0b011); } - static inline int OUT_C_H(Z80* ctx) { return ctx->OUT_C_R(0b100); } - static inline int OUT_C_L(Z80* ctx) { return ctx->OUT_C_R(0b101); } - static inline int OUT_C_0(Z80* ctx) { return ctx->OUT_C_R(0, true); } - static inline int OUT_C_A(Z80* ctx) { return ctx->OUT_C_R(0b111); } - inline int OUT_C_R(unsigned char r, bool zero = false) + static inline void OUT_C_B(Z80* ctx) { ctx->OUT_C_R(0b000); } + static inline void OUT_C_C(Z80* ctx) { ctx->OUT_C_R(0b001); } + static inline void OUT_C_D(Z80* ctx) { ctx->OUT_C_R(0b010); } + static inline void OUT_C_E(Z80* ctx) { ctx->OUT_C_R(0b011); } + static inline void OUT_C_H(Z80* ctx) { ctx->OUT_C_R(0b100); } + static inline void OUT_C_L(Z80* ctx) { ctx->OUT_C_R(0b101); } + static inline void OUT_C_0(Z80* ctx) { ctx->OUT_C_R(0, true); } + static inline void OUT_C_A(Z80* ctx) { ctx->OUT_C_R(0b111); } + inline void OUT_C_R(unsigned char r, bool zero = false) { if (zero) { - if (isDebug()) log("[%04X] OUT (%s), 0", reg.PC, registerDump(0b001)); + if (isDebug()) log("[%04X] OUT (%s), 0", reg.PC - 2, registerDump(0b001)); outPort(reg.pair.C, 0); } else { - unsigned char* rp = getRegisterPointer(r); - if (isDebug()) log("[%04X] OUT (%s), %s", reg.PC, registerDump(0b001), registerDump(r)); - outPort(reg.pair.C, *rp); + if (isDebug()) log("[%04X] OUT (%s), %s", reg.PC - 2, registerDump(0b001), registerDump(r)); + outPort(reg.pair.C, getRegister(r)); } - reg.PC += 2; - return 0; } // Load Output port (C) with location (HL), increment/decrement HL and decrement B - inline int repeatOUT(bool isIncHL, bool isRepeat) + inline void repeatOUT(bool isIncHL, bool isRepeat) { - unsigned short hl = getHL(); - unsigned char o = readByte(hl); + unsigned char o = readByte(getHL()); if (isDebug()) { if (isIncHL) { - log("[%04X] %s ... p(%s) <- (%s) <$%02x> [%s]", reg.PC, isRepeat ? "OUTIR" : "OUTI", registerDump(0b001), registerPairDump(0b10), o, registerDump(0b000)); + log("[%04X] %s ... p(%s) <- (%s) <$%02x> [%s]", reg.PC - 2, isRepeat ? "OUTIR" : "OUTI", registerDump(0b001), registerPairDump(0b10), o, registerDump(0b000)); } else { - log("[%04X] %s ... p(%s) <- (%s) <$%02x> [%s]", reg.PC, isRepeat ? "OUTDR" : "OUTD", registerDump(0b001), registerPairDump(0b10), o, registerDump(0b000)); + log("[%04X] %s ... p(%s) <- (%s) <$%02x> [%s]", reg.PC - 2, isRepeat ? "OUTDR" : "OUTD", registerDump(0b001), registerPairDump(0b10), o, registerDump(0b000)); } } outPort(reg.pair.C, o); decrementB_forRepeatIO(); reg.WZ = (unsigned short)(getBC() + (isIncHL ? 1 : -1)); - hl += isIncHL ? 1 : -1; - setHL(hl); + setHL((unsigned short)(getHL() + (isIncHL ? 1 : -1))); setFlagZ(reg.pair.B == 0); setFlagN(o & 0x80); // NOTE: ACTUAL FLAG CONDITION IS UNKNOWN setFlagH(reg.pair.L + o > 0xFF); // NOTE: ACTUAL FLAG CONDITION IS UNKNOWN setFlagC(isFlagH()); // NOTE: ACTUAL FLAG CONDITION IS UNKNOWN setFlagPV(((reg.pair.H + o) & 0x07) ^ reg.pair.B); // NOTE: ACTUAL FLAG CONDITION IS UNKNOWN if (isRepeat && 0 != reg.pair.B) { + reg.PC -= 2; consumeClock(5); - } else { - reg.PC += 2; } - return 0; } - static inline int OUTI(Z80* ctx) { return ctx->repeatOUT(true, false); } - static inline int OUTIR(Z80* ctx) { return ctx->repeatOUT(true, true); } - static inline int OUTD(Z80* ctx) { return ctx->repeatOUT(false, false); } - static inline int OUTDR(Z80* ctx) { return ctx->repeatOUT(false, true); } + static inline void OUTI(Z80* ctx) { ctx->repeatOUT(true, false); } + static inline void OUTIR(Z80* ctx) { ctx->repeatOUT(true, true); } + static inline void OUTD(Z80* ctx) { ctx->repeatOUT(false, false); } + static inline void OUTDR(Z80* ctx) { ctx->repeatOUT(false, true); } // Decimal Adjust Accumulator - inline int daa() + static inline void DAA(Z80* ctx) { ctx->daa(); } + inline void daa() { int a = reg.pair.A; bool c = isFlagC(); @@ -5553,16 +4977,13 @@ class Z80 setFlagH((a ^ reg.pair.A) & flagH()); setFlagPV(isEvenNumberBits(a)); setFlagC(c | ac); - if (isDebug()) log("[%04X] DAA ... A: $%02X -> $%02X", reg.PC, reg.pair.A, a); + if (isDebug()) log("[%04X] DAA ... A: $%02X -> $%02X", reg.PC - 1, reg.pair.A, a); reg.pair.A = a; - reg.PC++; - return 0; } - static inline int DAA(Z80* ctx) { return ctx->daa(); } // Rotate digit Left and right between Acc. and location (HL) - static inline int RLD_(Z80* ctx) { return ctx->RLD(); } - inline int RLD() + static inline void RLD_(Z80* ctx) { ctx->RLD(); } + inline void RLD() { unsigned short hl = getHL(); unsigned char beforeN = readByte(hl); @@ -5573,7 +4994,7 @@ class Z80 unsigned char beforeA = reg.pair.A; unsigned char afterA = (aH << 4) | nH; unsigned char afterN = (nL << 4) | aL; - if (isDebug()) log("[%04X] RLD ... A: $%02X -> $%02X, ($%04X): $%02X -> $%02X", reg.PC, beforeA, afterA, hl, beforeN, afterN); + if (isDebug()) log("[%04X] RLD ... A: $%02X -> $%02X, ($%04X): $%02X -> $%02X", reg.PC - 2, beforeA, afterA, hl, beforeN, afterN); reg.pair.A = afterA; writeByte(hl, afterN); setFlagS(reg.pair.A & 0x80); @@ -5582,13 +5003,12 @@ class Z80 setFlagH(false); setFlagPV(isEvenNumberBits(reg.pair.A)); setFlagN(false); - reg.PC += 2; - return consumeClock(2); + consumeClock(2); } // Rotate digit Right and right between Acc. and location (HL) - static inline int RRD_(Z80* ctx) { return ctx->RRD(); } - inline int RRD() + static inline void RRD_(Z80* ctx) { ctx->RRD(); } + inline void RRD() { unsigned short hl = getHL(); unsigned char beforeN = readByte(hl); @@ -5599,7 +5019,7 @@ class Z80 unsigned char beforeA = reg.pair.A; unsigned char afterA = (aH << 4) | nL; unsigned char afterN = (aL << 4) | nH; - if (isDebug()) log("[%04X] RRD ... A: $%02X -> $%02X, ($%04X): $%02X -> $%02X", reg.PC, beforeA, afterA, hl, beforeN, afterN); + if (isDebug()) log("[%04X] RRD ... A: $%02X -> $%02X, ($%04X): $%02X -> $%02X", reg.PC - 2, beforeA, afterA, hl, beforeN, afterN); reg.pair.A = afterA; writeByte(hl, afterN); setFlagS(reg.pair.A & 0x80); @@ -5608,8 +5028,7 @@ class Z80 setFlagH(false); setFlagPV(isEvenNumberBits(reg.pair.A)); setFlagN(false); - reg.PC += 2; - return consumeClock(2); + consumeClock(2); } int opLength1[256] = { @@ -5666,7 +5085,7 @@ class Z80 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, // E0 ~ EF 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 // F0 ~ FF }; - int (*opSet1[256])(Z80* ctx) = { + void (*opSet1[256])(Z80* ctx) = { NOP, LD_BC_NN, LD_BC_A, INC_RP_BC, INC_B, DEC_B, LD_B_N, RLCA, EX_AF_AF2, ADD_HL_BC, LD_A_BC, DEC_RP_BC, INC_C, DEC_C, LD_C_N, RRCA, DJNZ_E, LD_DE_NN, LD_DE_A, INC_RP_DE, INC_D, DEC_D, LD_D_N, RLA, JR_E, ADD_HL_DE, LD_A_DE, DEC_RP_DE, INC_E, DEC_E, LD_E_N, RRA, JR_NZ_E, LD_HL_NN, LD_ADDR_HL, INC_RP_HL, INC_H, DEC_H, LD_H_N, DAA, JR_Z_E, ADD_HL_HL, LD_HL_ADDR, DEC_RP_HL, INC_L, DEC_L, LD_L_N, CPL, @@ -5683,7 +5102,7 @@ class Z80 RET_C2, POP_DE, JP_C2_NN, OUT_N_A, CALL_C2_NN, PUSH_DE, SUB_N, RST10, RET_C3, EXX, JP_C3_NN, IN_A_N, CALL_C3_NN, OP_IX, SBC_N, RST18, RET_C4, POP_HL, JP_C4_NN, EX_SP_HL, CALL_C4_NN, PUSH_HL, AND_N, RST20, RET_C5, JP_HL, JP_C5_NN, EX_DE_HL, CALL_C5_NN, OP_ED, XOR_N, RST28, RET_C6, POP_AF, JP_C6_NN, DI, CALL_C6_NN, PUSH_AF, OR_N, RST30, RET_C7, LD_SP_HL, JP_C7_NN, EI, CALL_C7_NN, OP_IY, CP_N, RST38}; - int (*opSetCB[256])(Z80* ctx) = { + void (*opSetCB[256])(Z80* ctx) = { RLC_B, RLC_C, RLC_D, RLC_E, RLC_H, RLC_L, RLC_HL_, RLC_A, RRC_B, RRC_C, RRC_D, RRC_E, RRC_H, RRC_L, RRC_HL_, RRC_A, RL_B, RL_C, RL_D, RL_E, RL_H, RL_L, RL_HL_, RL_A, @@ -5716,7 +5135,7 @@ class Z80 SET_B_5, SET_C_5, SET_D_5, SET_E_5, SET_H_5, SET_L_5, SET_HL_5, SET_A_5, SET_B_6, SET_C_6, SET_D_6, SET_E_6, SET_H_6, SET_L_6, SET_HL_6, SET_A_6, SET_B_7, SET_C_7, SET_D_7, SET_E_7, SET_H_7, SET_L_7, SET_HL_7, SET_A_7}; - int (*opSetED[256])(Z80* ctx) = { + void (*opSetED[256])(Z80* ctx) = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, @@ -5735,7 +5154,7 @@ class Z80 LDD, CPD, IND, OUTD, nullptr, nullptr, nullptr, nullptr, LDIR, CPIR, INIR, OUTIR, nullptr, nullptr, nullptr, nullptr, LDDR, CPDR, INDR, OUTDR, nullptr, nullptr, nullptr, nullptr}; - int (*opSetIX[256])(Z80* ctx) = { + void (*opSetIX[256])(Z80* ctx) = { nullptr, nullptr, nullptr, nullptr, INC_B_2, DEC_B_2, LD_B_N_3, nullptr, nullptr, ADD_IX_BC, nullptr, nullptr, INC_C_2, DEC_C_2, LD_C_N_3, nullptr, nullptr, nullptr, nullptr, nullptr, INC_D_2, DEC_D_2, LD_D_N_3, nullptr, @@ -5765,10 +5184,10 @@ class Z80 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, POP_IX_, nullptr, EX_SP_IX_, nullptr, PUSH_IX_, nullptr, nullptr, - nullptr, JP_IX_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, JP_IX, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, LD_SP_IX_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; - int (*opSetIY[256])(Z80* ctx) = { + void (*opSetIY[256])(Z80* ctx) = { nullptr, nullptr, nullptr, nullptr, INC_B_2, DEC_B_2, LD_B_N_3, nullptr, nullptr, ADD_IY_BC, nullptr, nullptr, INC_C_2, DEC_C_2, LD_C_N_3, nullptr, nullptr, nullptr, nullptr, nullptr, INC_D_2, DEC_D_2, LD_D_N_3, nullptr, @@ -5798,10 +5217,10 @@ class Z80 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, POP_IY_, nullptr, EX_SP_IY_, nullptr, PUSH_IY_, nullptr, nullptr, - nullptr, JP_IY_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, JP_IY, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, LD_SP_IY_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; - int (*opSetIX4[256])(Z80* ctx, signed char d) = { + void (*opSetIX4[256])(Z80* ctx, signed char d) = { RLC_IX_with_LD_B, RLC_IX_with_LD_C, RLC_IX_with_LD_D, RLC_IX_with_LD_E, RLC_IX_with_LD_H, RLC_IX_with_LD_L, RLC_IX_, RLC_IX_with_LD_A, RRC_IX_with_LD_B, RRC_IX_with_LD_C, RRC_IX_with_LD_D, RRC_IX_with_LD_E, RRC_IX_with_LD_H, RRC_IX_with_LD_L, RRC_IX_, RRC_IX_with_LD_A, RL_IX_with_LD_B, RL_IX_with_LD_C, RL_IX_with_LD_D, RL_IX_with_LD_E, RL_IX_with_LD_H, RL_IX_with_LD_L, RL_IX_, RL_IX_with_LD_A, @@ -5834,7 +5253,7 @@ class Z80 SET_IX_5_with_LD_B, SET_IX_5_with_LD_C, SET_IX_5_with_LD_D, SET_IX_5_with_LD_E, SET_IX_5_with_LD_H, SET_IX_5_with_LD_L, SET_IX_5, SET_IX_5_with_LD_A, SET_IX_6_with_LD_B, SET_IX_6_with_LD_C, SET_IX_6_with_LD_D, SET_IX_6_with_LD_E, SET_IX_6_with_LD_H, SET_IX_6_with_LD_L, SET_IX_6, SET_IX_6_with_LD_A, SET_IX_7_with_LD_B, SET_IX_7_with_LD_C, SET_IX_7_with_LD_D, SET_IX_7_with_LD_E, SET_IX_7_with_LD_H, SET_IX_7_with_LD_L, SET_IX_7, SET_IX_7_with_LD_A}; - int (*opSetIY4[256])(Z80* ctx, signed char d) = { + void (*opSetIY4[256])(Z80* ctx, signed char d) = { RLC_IY_with_LD_B, RLC_IY_with_LD_C, RLC_IY_with_LD_D, RLC_IY_with_LD_E, RLC_IY_with_LD_H, RLC_IY_with_LD_L, RLC_IY_, RLC_IY_with_LD_A, RRC_IY_with_LD_B, RRC_IY_with_LD_C, RRC_IY_with_LD_D, RRC_IY_with_LD_E, RRC_IY_with_LD_H, RRC_IY_with_LD_L, RRC_IY_, RRC_IY_with_LD_A, RL_IY_with_LD_B, RL_IY_with_LD_C, RL_IY_with_LD_D, RL_IY_with_LD_E, RL_IY_with_LD_H, RL_IY_with_LD_L, RL_IY_, RL_IY_with_LD_A, @@ -5886,11 +5305,8 @@ class Z80 reg.R = ((reg.R + 1) & 0x7F) | (reg.R & 0x80); reg.IFF |= IFF_NMI(); reg.IFF &= ~IFF1(); - unsigned char pcL = reg.PC & 0x00FF; - unsigned char pcH = (reg.PC & 0xFF00) >> 8; - writeByte(reg.SP - 1, pcH); - writeByte(reg.SP - 2, pcL); - reg.SP -= 2; + push(getPCH(), 4); + push(getPCL(), 4); reg.PC = reg.interruptAddrN; consumeClock(11); invokeCallHandlers(); @@ -5918,16 +5334,11 @@ class Z80 RST(7, false); break; case 2: { // mode 2 - unsigned char pcL = reg.PC & 0x00FF; - unsigned char pcH = (reg.PC & 0xFF00) >> 8; - writeByte(reg.SP - 1, pcH); - writeByte(reg.SP - 2, pcL); + writeByte(reg.SP - 1, getPCH()); + writeByte(reg.SP - 2, getPCL()); reg.SP -= 2; - unsigned short addr = reg.I; - addr <<= 8; - addr |= reg.interruptVector; - unsigned short pc = readByte(addr); - pc += ((unsigned short)readByte(addr + 1)) << 8; + unsigned short addr = make16BitsFromLE(reg.interruptVector, reg.I); + unsigned short pc = make16BitsFromLE(readByte(addr), readByte(addr + 1)); if (isDebug()) log("EXECUTE INT MODE2: ($%04X) = $%04X", addr, pc); reg.PC = pc; consumeClock(3); @@ -5970,11 +5381,24 @@ class Z80 std::function out, bool returnPortAs16Bits = false) { - this->CB.read.setupAsFunctionObject(read); - this->CB.write.setupAsFunctionObject(write); - this->CB.in.setupAsFunctionObject(in); - this->CB.out.setupAsFunctionObject(out); - this->CB.returnPortAs16Bits = returnPortAs16Bits; + setupMemoryCallback(read, write); + setupDeviceCallback(in, out, returnPortAs16Bits); + } + + void setupMemoryCallback(std::function read, + std::function write) + { + CB.read.setupAsFunctionObject(read); + CB.write.setupAsFunctionObject(write); + } + + void setupDeviceCallback(std::function in, + std::function out, + bool returnPortAs16Bits) + { + CB.in.setupAsFunctionObject(in); + CB.out.setupAsFunctionObject(out); + CB.returnPortAs16Bits = returnPortAs16Bits; } void setupCallbackFP(unsigned char (*read)(void* arg, unsigned short addr), @@ -5983,11 +5407,24 @@ class Z80 void (*out)(void* arg, unsigned short port, unsigned char value), bool returnPortAs16Bits = false) { - this->CB.read.setupAsFunctionPointer(read); - this->CB.write.setupAsFunctionPointer(write); - this->CB.in.setupAsFunctionPointer(in); - this->CB.out.setupAsFunctionPointer(out); - this->CB.returnPortAs16Bits = returnPortAs16Bits; + setupMemoryCallbackFP(read, write); + setupDeviceCallbackFP(in, out, returnPortAs16Bits); + } + + void setupMemoryCallbackFP(unsigned char (*read)(void* arg, unsigned short addr), + void (*write)(void* arg, unsigned short addr, unsigned char value)) + { + CB.read.setupAsFunctionPointer(read); + CB.write.setupAsFunctionPointer(write); + } + + void setupDeviceCallbackFP(unsigned char (*in)(void* arg, unsigned short addr), + void (*out)(void* arg, unsigned short addr, unsigned char value), + bool returnPortAs16Bits) + { + CB.in.setupAsFunctionPointer(in); + CB.out.setupAsFunctionPointer(out); + CB.returnPortAs16Bits = returnPortAs16Bits; } void initialize() @@ -6009,12 +5446,14 @@ class Z80 removeAllReturnHandlers(); } - void setDebugMessage(const std::function& debugMessage) + template + void setDebugMessage(Functor debugMessage) { CB.debugMessageEnabled = true; CB.debugMessage.setupAsFunctionObject(debugMessage); } + void setDebugMessage(void (*debugMessage)(void* arg, const char* msg)) { setDebugMessageFP(debugMessage); } void setDebugMessageFP(void (*debugMessage)(void* arg, const char* msg)) { CB.debugMessageEnabled = true; @@ -6031,13 +5470,38 @@ class Z80 return CB.debugMessageEnabled; } - void addBreakPoint(unsigned short addr, const std::function& callback) + inline unsigned short make16BitsFromLE(unsigned char low, unsigned char high) + { + unsigned short n = high; + n <<= 8; + n |= low; + return n; + } + + inline void splitTo8BitsPair(unsigned short value, unsigned char* high, unsigned char* low) + { + *high = (value & 0xFF00) >> 8; + *low = value & 0xFF; + } + + template + void addBreakPoint(unsigned short addr, Functor callback) + { + auto it = CB.breakPoints.find(addr); + if (it == CB.breakPoints.end()) { + CB.breakPoints[addr] = new std::vector(); + } + CB.breakPoints[addr]->push_back(new BreakPointFC(addr, callback)); + } + + void addBreakPoint(unsigned short addr, void (*callback)(void*)) { addBreakPointFP(addr, callback); } + void addBreakPointFP(unsigned short addr, void (*callback)(void*)) { auto it = CB.breakPoints.find(addr); if (it == CB.breakPoints.end()) { CB.breakPoints[addr] = new std::vector(); } - CB.breakPoints[addr]->push_back(new BreakPoint(addr, callback)); + CB.breakPoints[addr]->push_back(new BreakPointFP(addr, callback)); } void removeBreakPoint(unsigned short addr) @@ -6066,31 +5530,52 @@ class Z80 if (it == CB.breakOperands.end()) { CB.breakOperands[operandNumber] = new std::vector(); } - CB.breakOperands[operandNumber]->push_back(new BreakOperand(prefixNumber, operandNumber, callback)); + CB.breakOperands[operandNumber]->push_back(new BreakOperandFC(prefixNumber, operandNumber, callback)); } - void addBreakOperand(unsigned char operandNumber, const std::function& callback) + template + void addBreakOperand(unsigned char operandNumber, Functor callback) { addBreakOperand_(0, (int)operandNumber, callback); } - void addBreakOperand(unsigned char prefixNumber, unsigned char operandNumber, const std::function& callback) + template + void addBreakOperand(unsigned char prefixNumber, unsigned char operandNumber, Functor callback) + { + addBreakOperand_((int)prefixNumber, make16BitsFromLE(operandNumber, prefixNumber), callback); + } + + template + void addBreakOperand(unsigned char prefixNumber1, unsigned char prefixNumber2, unsigned char operandNumber, Functor callback) { - int n = prefixNumber; + int n = make16BitsFromLE(prefixNumber2, prefixNumber1); + int prefixNumber = n; n <<= 8; n |= operandNumber; - addBreakOperand_((int)prefixNumber, n, callback); + addBreakOperand_(prefixNumber, n, callback); } - void addBreakOperand(unsigned char prefixNumber1, unsigned char prefixNumber2, unsigned char operandNumber, const std::function& callback) + void addBreakOperandFP_(int prefixNumber, int operandNumber, void (*callback)(void*, unsigned char*, int)) { - int n = prefixNumber1; - n <<= 8; - n |= prefixNumber2; + auto it = CB.breakOperands.find(operandNumber); + if (it == CB.breakOperands.end()) { + CB.breakOperands[operandNumber] = new std::vector(); + } + CB.breakOperands[operandNumber]->push_back(new BreakOperandFP(prefixNumber, operandNumber, callback)); + } + + void addBreakOperand(unsigned char operandNumber, void (*callback)(void*, unsigned char*, int)) { addBreakOperandFP(operandNumber, callback); } + void addBreakOperandFP(unsigned char operandNumber, void (*callback)(void*, unsigned char*, int)) { addBreakOperandFP_(0, (int)operandNumber, callback); } + void addBreakOperand(unsigned char prefixNumber, unsigned char operandNumber, void (*callback)(void*, unsigned char*, int)) { addBreakOperandFP(prefixNumber, operandNumber, callback); } + void addBreakOperandFP(unsigned char prefixNumber, unsigned char operandNumber, void (*callback)(void*, unsigned char*, int)) { addBreakOperandFP_((int)prefixNumber, make16BitsFromLE(operandNumber, prefixNumber), callback); } + void addBreakOperand(unsigned char prefixNumber1, unsigned char prefixNumber2, unsigned char operandNumber, void (*callback)(void*, unsigned char*, int)) { addBreakOperandFP(prefixNumber1, prefixNumber2, operandNumber, callback); } + void addBreakOperandFP(unsigned char prefixNumber1, unsigned char prefixNumber2, unsigned char operandNumber, void (*callback)(void*, unsigned char*, int)) + { + int n = make16BitsFromLE(prefixNumber2, prefixNumber1); int prefixNumber = n; n <<= 8; n |= operandNumber; - addBreakOperand_(prefixNumber, n, callback); + addBreakOperandFP_(prefixNumber, n, callback); } void removeBreakOperand(int operandNumber) @@ -6104,17 +5589,12 @@ class Z80 void removeBreakOperand(unsigned char prefixNumber, unsigned char operandNumber) { - int n = prefixNumber; - n <<= 8; - n |= operandNumber; - removeBreakOperand(n); + removeBreakOperand(make16BitsFromLE(operandNumber, prefixNumber)); } void removeBreakOperand(unsigned char prefixNumber1, unsigned char prefixNumber2, unsigned char operandNumber) { - int n = prefixNumber1; - n <<= 8; - n |= prefixNumber2; + int n = make16BitsFromLE(prefixNumber2, prefixNumber1); n <<= 8; n |= operandNumber; removeBreakOperand(n); @@ -6131,10 +5611,10 @@ class Z80 } } - void addReturnHandler(const std::function& callback) - { - CB.returnHandlers.push_back(new ReturnHandler(callback)); - } + template + void addReturnHandler(Functor callback) { CB.returnHandlers.push_back(new SimpleHandlerFC(callback)); } + void addReturnHandler(void (*callback)(void*)) { addReturnHandlerFP(callback); } + void addReturnHandlerFP(void (*callback)(void*)) { CB.returnHandlers.push_back(new SimpleHandlerFP(callback)); } void removeAllReturnHandlers() { @@ -6142,10 +5622,10 @@ class Z80 CB.returnHandlers.clear(); } - void addCallHandler(const std::function& callback) - { - CB.callHandlers.push_back(new CallHandler(callback)); - } + template + void addCallHandler(Functor callback) { CB.callHandlers.push_back(new SimpleHandlerFC(callback)); } + void addCallHandler(void (*callback)(void*)) { addCallHandlerFP(callback); } + void addCallHandlerFP(void (*callback)(void*)) { CB.callHandlers.push_back(new SimpleHandlerFP(callback)); } void removeAllCallHandlers() { @@ -6153,16 +5633,18 @@ class Z80 CB.callHandlers.clear(); } - void setConsumeClockCallbackFP(void (*consumeClock_)(void* arg, int clocks)) + template + void setConsumeClockCallback(Functor consumeClock_) { CB.consumeClockEnabled = true; - CB.consumeClock.setupAsFunctionPointer(consumeClock_); + CB.consumeClock.setupAsFunctionObject(consumeClock_); } - void setConsumeClockCallback(const std::function& consumeClock_) + void setConsumeClockCallback(void (*consumeClock_)(void* arg, int clocks)) { setConsumeClockCallbackFP(consumeClock_); } + void setConsumeClockCallbackFP(void (*consumeClock_)(void* arg, int clocks)) { CB.consumeClockEnabled = true; - CB.consumeClock.setupAsFunctionObject(consumeClock_); + CB.consumeClock.setupAsFunctionPointer(consumeClock_); } void resetConsumeClockCallback() @@ -6192,6 +5674,13 @@ class Z80 reg.interruptAddrN = addr; } + inline unsigned char fetch(int clocks) + { + unsigned char result = readByte(reg.PC, clocks); + reg.PC++; + return result; + } + inline int execute(int clock) { int executed = 0; @@ -6203,16 +5692,13 @@ class Z80 reg.execEI = 0; readByte(reg.PC); // NOTE: read and discard (to be consumed 4Hz) } else { - if (wtc.fretch) consumeClock(wtc.fretch); + if (wtc.fetch) consumeClock(wtc.fetch); checkBreakPoint(); reg.execEI = 0; - int operandNumber = readByte(reg.PC, 2); + int operandNumber = fetch(2); updateRefreshRegister(); checkBreakOperand(operandNumber); - if (opSet1[operandNumber](this) < 0) { - if (isDebug()) log("[%04X] detected an invalid operand: $%02X", reg.PC, operandNumber); - return 0; - } + opSet1[operandNumber](this); } executed += reg.consumeClockCounter; clock -= reg.consumeClockCounter;