📄 cpu.pas
字号:
unit cpu;
//{$DEFINE debug}
interface
uses
SysUtils;
type
TPS = record
nf: byte; //negative flag
off: byte; //overflow flag
uf:Byte;
bf: byte; //break flag
dm: byte; //decimal mode
id: byte; //interrupt disable
zf: byte; //zero flag
cf: byte; //carry flag
end;
TCPU = class
pc: word; //program counter
sp: word; //stack pointer
a: byte; //accumulator
x: byte; //index register
y: byte; //index register
Ps: tps; //processor status
run: boolean;
toggle: boolean;
curIns: string;
CPU_Mem: array[0..$7FFF] of byte;
memread: function(address: word): byte;
memwrite: procedure(address: word; data: byte);
function CpuRun(var cycles: integer): boolean;
procedure Reset;
procedure NMI(var cc: integer);
private
procedure pswtops(psw: byte);
function psTopsw(): byte;
procedure setnz(data: byte);
procedure push(data: byte);
function pop: byte;
function pscombine: byte;
procedure pssplit(p: byte);
function ZpAddress(pos:Word):Word;
function IzpAddress(Pos:Word;offset:Byte):Word; //index zero page;
function AbAddress(Pos:Word):Word;//absolute
function IABAddress(Pos:Word;offset:Byte):Word;//indexed absolute
function IIXAddress(Pos:Word;x:Byte):Word;//indexed indirect ($xx,X)
function IIYAddress(Pos:Word;y:Byte):Word;// indirect indexed ($xx),Y
end;
implementation
var
BrkVector: word;
ResetVector: word;
NMIVector: word;
{ TCPU }
function TCPU.CpuRun(var cycles: integer): boolean;
var
tempbyte, inst: byte;
psw, acc, xr, yr,tempflag: byte;
offset: shortint;
taddr: word;
begin
psw := 0;
inst := memread(pc);
case inst of
//* *
//* adc instruction 2005/12/20 *
//*---------------start-------------------*
$69: //ADC - Add with Carry Immediate
begin
tempbyte := memread(pc + 1);
{$IFDEF debug}
curIns := 'ADC #$' + intToHex(tempbyte, 0);
{$ENDIF}
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
Inc(pc, 2);
inc(cycles, 2);
end;
$65: //ADC - Add with Carry Zero Page
begin
taddr:=ZpAddress(pc);
tempbyte := memread(taddr); //zero page
{$IFDEF debug}
curIns := 'ADC $' + intToHex(taddr, 0);
{$ENDIF}
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
inc(cycles, 3);
inc(pc, 2);
end;
$75: //ADC - Add with Carry Zero Page,X
begin
tempbyte := memread(izpaddress(pc,x)); //Zero Page,X
{$IFDEF debug}
curIns := 'ADC $' + intToHex(memread(pc + 1), 0) + ',X';
{$ENDIF}
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
inc(cycles, 4);
inc(pc, 2);
end;
$6D: //ADC - Add with Carry absolute
begin
taddr:=AbAddress(pc);
tempbyte := memread(taddr);
{$IFDEF debug}
curIns := 'ADC $' + intToHex(taddr, 0);
{$ENDIF}
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
inc(pc, 3);
inc(cycles, 4);
end;
$7D: //ADC - Add with Carry absolute,x
begin
taddr:=IABAddress(pc,x);
tempbyte := memread(taddr);
{$IFDEF debug}
curIns := 'ADC $' + intToHex(taddr-x, 0) + ',X';
{$ENDIF}
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
inc(cycles, 4);
inc(pc, 3);
end;
$79: //ADC - Add with Carry absolute,y
begin
taddr:=IABAddress(pc,y);
tempbyte := memread(taddr);
{$IFDEF debug}
curIns := 'ADC $' + intToHex(taddr-y, 0) + ' ' + ',Y';
{$ENDIF}
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
inc(cycles, 4);
inc(pc, 3);
end;
$61: //ADC - Add with Carry (Indirect,X)
begin
tempbyte := memread(iixaddress(pc,x));
{$IFDEF debug}
curIns := 'ADC ($' + intToHex(memread(pc + 1), 0) + ',X)';
{$ENDIF}
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
inc(cycles, 6);
inc(pc, 2);
end;
$71: //ADC - Add with Carry (Indirect),Y
begin
{$IFDEF debug}
curIns := 'ADC ($' + intToHex(memread(pc + 1), 0) + '),Y ';
{$ENDIF}
tempbyte := memread(iiyaddress(pc,y));;
acc := a;
psw := psTopsw;
asm
mov ah,psw
sahf
mov al,acc
adc al,tempbyte
lahf
mov psw,ah
jno @quit
or psw,$20
@quit:
mov acc,al
end;
a := acc;
pswtops(psw);
inc(cycles, 6);
inc(pc, 2);
end;
//* *
//* adc instruction 2005/12/20 *
//*---------------end---------------------*
//* *
//* and instruction 2005/12/21 *
//*---------------start-------------------*
$29: //AND immediate
begin
{$IFDEF debug}
curIns := 'AND #$' + intToHex(memread(pc + 1), 0);
{$ENDIF}
tempbyte := memread(pc + 1);
a := a and tempbyte;
setnz(a);
inc(cycles, 2);
inc(pc, 2);
end;
$25: //AND zero page
begin
taddr:=ZpAddress(pc);
{$IFDEF debug}
curIns := 'AND $' + intToHex(taddr, 0);
{$ENDIF}
tempbyte := memread(taddr);
a := a and tempbyte;
inc(cycles, 3);
inc(pc, 2);
setnz(a);
end;
$35: //AND zero page x
begin
{$IFDEF debug}
curIns := 'AND $' + intToHex(memread(pc + 1), 0) + ',X';
{$ENDIF}
tempbyte := memread(izpaddress(pc,x));
a := a and tempbyte;
setnz(a);
inc(cycles, 4);
inc(pc, 2);
end;
$2D: //AND absolute
begin
taddr:=AbAddress(pc);
tempbyte :=memread(taddr);
{$IFDEF debug}
curIns := 'AND $' + intToHex(taddr, 0);
{$ENDIF}
a := a and tempbyte;
setnz(a);
inc(cycles, 4);
inc(pc, 3);
end;
$3D: //AND absolute x
begin
taddr:=IABAddress(pc,x);
tempbyte := memread(taddr);
{$IFDEF debug}
curIns := 'AND $' + intToHex(taddr-x, 0) + ',X';
{$ENDIF}
a := a and tempbyte;
setnz(a);
inc(cycles, 4);
inc(pc, 3);
end;
$39: //AND absolute y
begin
taddr:=IABAddress(pc,y);
tempbyte := memread(taddr);
{$IFDEF debug}
curIns := 'AND $' + intToHex(taddr-y, 0) + ',Y';
{$ENDIF}
a := a and tempbyte;
setnz(a);
inc(cycles, 4);
inc(pc, 3);
end;
$21: //AND (indirect.x)
begin
{$IFDEF debug}
curIns := 'AND ($' + intToHex(memread(pc + 1), 0) + ',X)';
{$ENDIF}
tempbyte :=memread(iixaddress(pc,x));
a := a and tempbyte;
setnz(a);
inc(cycles, 6);
inc(pc, 2);
end;
$31: //AND (indirect).y
begin
{$IFDEF debug}
curIns := 'AND ($' + intToHex(memread(pc + 1), 0) + '),Y';
{$ENDIF}
tempbyte := memread(IIYaddress(pc,y));
a := a and tempbyte;
setnz(a);
inc(cycles, 5);
inc(pc, 2);
end;
//* *
//* and instruction 2005/12/21 *
//*---------------end---------------------*
//* *
//* asl instruction 2005/12/21 *
//*---------------start-------------------*
$0A: //asl accumulator
begin
{$IFDEF debug}
curIns := 'ASL';
{$ENDIF}
ps.cf := a and $80;
ps.cf := ps.cf shr 7;
acc := a;
asm
shl acc,1;
end;
a := acc;
setnz(a);
inc(cycles, 2);
inc(pc);
end;
$06: //asl zero page
begin
taddr:=ZpAddress(pc);
tempbyte:=memread(taddr);
{$IFDEF debug}
curIns := 'ASL $ ' + intToHex(taddr, 0) + ' zp ';
{$ENDIF}
ps.cf := tempbyte and $80;
ps.cf := ps.cf shr 7;
asm
shl tempbyte,1;
end;
setnz(tempbyte);
memwrite(taddr, tempbyte);
inc(cycles, 5);
inc(pc, 2);
end;
$16: //asl zero page.x
begin
taddr:=IzpAddress(pc,x);
tempbyte:=memread(taddr);
{$IFDEF debug}
curIns := 'ASL $' + intToHex(memread(pc + 1), 0) + ',X';
{$ENDIF}
ps.cf := tempbyte and $80;
ps.cf := ps.cf shr 7;
asm
shl tempbyte,1;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -