Ich habe nun die CPU Unit in ein einfachen Projekt kopiert und dort mal im Release Mode (-O3) kompiliert.
Diese case of Struktur:
Code: Alles auswählen
procedure TZ180Cpu.execOp00Codes;
...
case (opCode) of
$00: begin // OP-Code 0x00 : NOP
machineCycles := 1;
clockCycles := 3;
end;
$01: begin // OP-Code 0x01 : LD BC,nn;
regBC.C := memRead(regPC.Value);
Inc(regPC.Value);
regBC.B := memRead(regPC.Value);
Inc(regPC.Value);
machineCycles := 3;
clockCycles := 9;
end;
$02: begin // OP-Code 0x02 : LD (BC),A
memWrite(regBC.Value, regAF.A);
machineCycles := 3;
clockCycles := 7;
end;
$03: begin // OP-Code 0x03 : INC BC
Inc(regBC.Value);
machineCycles := 2;
clockCycles := 4;
end;
$04: begin // OP-Code 0x04 : INC B
inc8Bit(regBC.B);
machineCycles := 2;
clockCycles := 4;
end;
$05: begin // OP-Code 0x05 : DEC B
dec8Bit(regBC.B);
machineCycles := 2;
clockCycles := 4;
end;
$06: begin // OP-Code 0x06 : LD B,n
regBC.B := memRead(regPC.Value);
Inc(regPC.Value);
machineCycles := 2;
clockCycles := 6;
end;
....
$FE: begin // OP-Code 0xFE : CP n
cpA8Bit(memRead(regPC.Value));
Inc(regPC.Value);
machineCycles := 2;
clockCycles := 6;
end;
$FF: begin // OP-Code 0xFF : RST 38H
push(regPC.Value);
regPC.Value := $0038;
machineCycles := 5;
clockCycles := 11;
end;
end;
wird wie folgt übersetzt:
Code: Alles auswählen
.section .data.rel.n_Z180_CPU$_$TZ180CPU_$__$$_EXECOP00CODES
.balign 4
.Ld1:
.long .Lj103-.Ld1
.long .Lj104-.Ld1
.long .Lj105-.Ld1
.long .Lj106-.Ld1
.long .Lj107-.Ld1
.long .Lj108-.Ld1
.long .Lj109-.Ld1
.long .Lj110-.Ld1
.long .Lj111-.Ld1
...
.long .Lj354-.Ld1
.long .Lj355-.Ld1
.long .Lj356-.Ld1
.long .Lj357-.Ld1
.long .Lj358-.Ld1
Das sieht sehr nach einer JumpTable aus. Diese case of Struktur ist auch sauber von $00 - $FF ausgefüllt.
Dagegen wird diese case of Struktur:
Code: Alles auswählen
procedure TZ180Cpu.execOpDdCodes;
...
case (opCode) of
$09: begin // OP-Code 0xDD09 : ADD IX,BC
addIX16Bit(regBC.Value);
machineCycles := 6;
clockCycles := 10;
end;
$19: begin // OP-Code 0xDD19 : ADD IX,DE
addIX16Bit(regDE.Value);
machineCycles := 6;
clockCycles := 10;
end;
$21: begin // OP-Code 0xDD21 : LD IX,nn
regIX.low := memRead(regPC.Value);
Inc(regPC.Value);
regIX.high := memRead(regPC.Value);
Inc(regPC.Value);
machineCycles := 4;
clockCycles := 12;
end;
$22: begin // OP-Code 0xDD22 : LD (nn),IX
tmpWord.low := memRead(regPC.Value);
Inc(regPC.Value);
tmpWord.high := memRead(regPC.Value);
Inc(regPC.Value);
memWrite(tmpWord.Value, regIX.low);
memWrite(tmpWord.Value + 1, regIX.high);
machineCycles := 7;
clockCycles := 19;
end;
$23: begin // OP-Code 0xDD23 : INC IX
Inc(regIX.Value);
machineCycles := 3;
clockCycles := 7;
end;
$29: begin // OP-Code 0xDD29 : ADD IX,IX
addIX16Bit(regIX.Value);
machineCycles := 6;
clockCycles := 10;
end;
$2A: begin // OP-Code 0xDD2A : LD IX,(nn)
tmpWord.low := memRead(regPC.Value);
Inc(regPC.Value);
tmpWord.high := memRead(regPC.Value);
Inc(regPC.Value);
regIX.low := memRead(tmpWord.Value);
regIX.high := memRead(tmpWord.Value + 1);
machineCycles := 6;
clockCycles := 18;
end;
...
so übersetzt:
Code: Alles auswählen
.section .text.n_z180_cpu$_$tz180cpu_$__$$_execopddcodes
.balign 16,0x90
.globl Z180_CPU$_$TZ180CPU_$__$$_EXECOPDDCODES
.type Z180_CPU$_$TZ180CPU_$__$$_EXECOPDDCODES,@function
Z180_CPU$_$TZ180CPU_$__$$_EXECOPDDCODES:
.Lc95:
# [3869] begin
pushq %rbx
pushq %r12
leaq -8(%rsp),%rsp
.Lc97:
# Var opCode located in register al
# Var memOffset located in register r12b
# Var tmpByte located at rsp+0, size=OS_8
# Var tmpWord located at rsp+4, size=OS_16
movq %rdi,%rbx
# Var $self located in register rbx
# [3870] opCode := readOpCode(regPC.Value);
movzwl 48(%rbx),%eax
# Var $self located in register rbx
movq %rbx,%rax
movl 16(%rax),%ecx
movl 24(%rax),%edx
addl %ecx,%edx
movl %edx,16(%rax)
# Var opCode located in register al
# [3871] Inc(regPC.Value);
addw $1,48(%rbx)
# [3872] case (opCode) of
cmpb $9,%al
jb .Lj749
subb $9,%al
je .Lj750
subb $16,%al
je .Lj751
subb $8,%al
je .Lj752
subb $1,%al
je .Lj753
subb $1,%al
je .Lj754
subb $6,%al
je .Lj755
subb $1,%al
je .Lj756
subb $1,%al
je .Lj757
subb $9,%al
je .Lj758
...
das scheint einfach eine Reihe von vergleichen zu sein.
Wenn ich jetzt jede case of Struktur mit 256 (opCode ist vom Typ Byte) Abfragen erstelle sollte doch dann immer eine JumpTable herauskommen, oder sehe ich das falsch?
Wäre auf jeden fall einfacher zu lösen als die ganze Unit als JumpTable umzuschreiben.
Grüße
HobbyProgrammer
Host: Core i7-12700H, NVIDIA RTX3050 6GB, 32GB Ram, 1TB NVME SSD mit KUbuntu 24.04LTS 64bit , VM KUbuntu 22.04 LTS 64bit mit Lazarus 3.6 und Cross-Platform Compiler für Linux 32/64bit und Windows 32/64bit. Wine für erste Tests der Windows Binarys.