1
0
mirror of https://github.com/t-edson/P65Utils.git synced 2024-06-09 18:29:29 +00:00

Add files via upload

This commit is contained in:
Tito Hinostroza 2020-02-27 23:46:25 -05:00 committed by GitHub
parent 729875617f
commit 4205b2147d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 396 additions and 348 deletions

View File

@ -99,14 +99,13 @@ type
maxUsed : dword; //Dirección mayor de la ROM usdas maxUsed : dword; //Dirección mayor de la ROM usdas
hexLines : TStringList; //Uusado para crear archivo *.hex hexLines : TStringList; //Uusado para crear archivo *.hex
public //Memories public //Memories
ram : TCPURam; //memoria RAM ram : TCPURam; //RAM memory
iRam : integer; //puntero a la memoria RAM, para escribir cuando se ensambla o compila código. iRam : integer; //puntero a la memoria RAM, para escribir cuando se ensambla o compila código.
function DisassemblerAt(addr: word; out nBytesProc: byte; useVarName: boolean function DisassemblerAt(addr: word; out nBytesProc: byte; useVarName: boolean
): string; virtual; abstract; //Desensambla la instrucción actual ): string; virtual; abstract; //Desensambla la instrucción actual
public //RAM memory functions public //RAM memory functions
hasDataAdrr: integer; //Flag/index to indicate a Data block has defined. dataAddr1: integer; //Start address for Data variables (-1 if not used). Used too as flag.
dataAddr1: integer; //Start address for Data variables (-1 if not used) dataAddr2: integer; //End address for Data variables (-1 if not used)
dataAddr2: integer;
procedure ClearMemRAM; procedure ClearMemRAM;
procedure DisableAllRAM; procedure DisableAllRAM;
procedure SetStatRAM(i1, i2: word; status0: TCPUCellState); procedure SetStatRAM(i1, i2: word; status0: TCPUCellState);
@ -129,7 +128,7 @@ type
procedure Exec; virtual; abstract; //Ejecuta instrucción actual procedure Exec; virtual; abstract; //Ejecuta instrucción actual
procedure ExecTo(endAdd: word); virtual; abstract; //Ejecuta hasta cierta dirección procedure ExecTo(endAdd: word); virtual; abstract; //Ejecuta hasta cierta dirección
procedure ExecStep; virtual; abstract; //Execute one instruction considering CALL as one instruction procedure ExecStep; virtual; abstract; //Execute one instruction considering CALL as one instruction
procedure ExecNCycles(nCyc: integer; out stopped: boolean); virtual; abstract; //Ejecuta hasta cierta dirección procedure ExecNCycles(nCyc: integer; out stopped: boolean); virtual; abstract; //Execute "n" cycles
procedure Reset(hard: boolean); virtual; abstract; procedure Reset(hard: boolean); virtual; abstract;
function ReadPC: dword; virtual; abstract; //Defined DWORD to cover the 18F PC register function ReadPC: dword; virtual; abstract; //Defined DWORD to cover the 18F PC register
procedure WritePC(AValue: dword); virtual; abstract; procedure WritePC(AValue: dword); virtual; abstract;
@ -312,7 +311,7 @@ begin
com := UpCase(trim(strDef)); com := UpCase(trim(strDef));
if com='' then begin if com='' then begin
hasDataAdrr := -1; //Disable dataAddr1 := -1; //Disable
exit; exit;
end; end;
//Find Address1 //Find Address1
@ -328,7 +327,6 @@ begin
exit(false); exit(false);
end; end;
//Ya se tienen los parámetros, para definir la memoria //Ya se tienen los parámetros, para definir la memoria
hasDataAdrr := add1; //Set flag
dataAddr1 := add1; //Save dataAddr1 := add1; //Save
dataAddr2 := add2; //Save end dataAddr2 := add2; //Save end
end; end;
@ -466,7 +464,7 @@ end;
//Initialization //Initialization
constructor TCPUCore.Create; constructor TCPUCore.Create;
begin begin
hasDataAdrr := -1; //Disable dataAddr1 := -1; //Disable
hexLines := TStringList.Create; hexLines := TStringList.Create;
frequen := 1000000; //4MHz frequen := 1000000; //4MHz
end; end;

View File

@ -1,3 +1,8 @@
0.3
===
Se elimina la bandera hasDataAdrr y se pasa a usar dataAddr1, como bandera y dirección inicial.
Se corrige un error en la ejecución de la instrucción ROL.
0.2 0.2
=== ===
Se cambian variables a tipo dword para evitar desborde en TP6502.GetFreeBytes(). Se cambian variables a tipo dword para evitar desborde en TP6502.GetFreeBytes().

View File

@ -12,7 +12,7 @@
<WindowIndex Value="-1"/> <WindowIndex Value="-1"/>
<TopLine Value="-1"/> <TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/> <CursorPos X="-1" Y="-1"/>
<UsageCount Value="61"/> <UsageCount Value="74"/>
</Unit0> </Unit0>
<Unit1> <Unit1>
<Filename Value="unit1.pas"/> <Filename Value="unit1.pas"/>
@ -21,19 +21,19 @@
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<UnitName Value="Unit1"/> <UnitName Value="Unit1"/>
<IsVisibleTab Value="True"/>
<TopLine Value="135"/> <TopLine Value="135"/>
<CursorPos X="20" Y="154"/> <CursorPos X="20" Y="154"/>
<UsageCount Value="61"/> <UsageCount Value="74"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<LoadedDesigner Value="True"/> <LoadedDesigner Value="True"/>
</Unit1> </Unit1>
<Unit2> <Unit2>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="1"/> <EditorIndex Value="1"/>
<TopLine Value="178"/> <TopLine Value="171"/>
<CursorPos X="15" Y="202"/> <CursorPos Y="171"/>
<UsageCount Value="32"/> <UsageCount Value="38"/>
<Bookmarks Count="1"> <Bookmarks Count="1">
<Item0 Y="1211" ID="1"/> <Item0 Y="1211" ID="1"/>
</Bookmarks> </Bookmarks>
@ -42,9 +42,9 @@
<Unit3> <Unit3>
<Filename Value="..\CPUCore.pas"/> <Filename Value="..\CPUCore.pas"/>
<EditorIndex Value="2"/> <EditorIndex Value="2"/>
<TopLine Value="98"/> <TopLine Value="124"/>
<CursorPos X="31" Y="121"/> <CursorPos X="31" Y="121"/>
<UsageCount Value="25"/> <UsageCount Value="31"/>
<Bookmarks Count="1"> <Bookmarks Count="1">
<Item0 Y="117" ID="3"/> <Item0 Y="117" ID="3"/>
</Bookmarks> </Bookmarks>
@ -55,123 +55,127 @@
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="2838"/> <TopLine Value="2838"/>
<CursorPos Y="2861"/> <CursorPos Y="2861"/>
<UsageCount Value="10"/> <UsageCount Value="9"/>
</Unit4> </Unit4>
</Units> </Units>
<JumpHistory Count="29" HistoryIndex="28"> <JumpHistory Count="30" HistoryIndex="29">
<Position1> <Position1>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="259" Column="21" TopLine="218"/> <Caret Line="355" Column="65" TopLine="252"/>
</Position1> </Position1>
<Position2> <Position2>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="355" Column="65" TopLine="252"/> <Caret Line="368" Column="5" TopLine="265"/>
</Position2> </Position2>
<Position3> <Position3>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="368" Column="5" TopLine="265"/> <Caret Line="373" Column="32" TopLine="265"/>
</Position3> </Position3>
<Position4> <Position4>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="373" Column="32" TopLine="265"/> <Caret Line="1060" Column="49" TopLine="963"/>
</Position4> </Position4>
<Position5> <Position5>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="1060" Column="49" TopLine="963"/> <Caret Line="1085" Column="49" TopLine="1064"/>
</Position5> </Position5>
<Position6> <Position6>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="1085" Column="49" TopLine="1064"/>
</Position6> </Position6>
<Position7> <Position7>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="370" Column="8" TopLine="354"/>
</Position7> </Position7>
<Position8> <Position8>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="370" Column="8" TopLine="354"/> <Caret Line="369" Column="28" TopLine="354"/>
</Position8> </Position8>
<Position9> <Position9>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="369" Column="28" TopLine="354"/> <Caret Line="1148" TopLine="1141"/>
</Position9> </Position9>
<Position10> <Position10>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="1148" TopLine="1141"/> <Caret Line="207" Column="33" TopLine="180"/>
</Position10> </Position10>
<Position11> <Position11>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="207" Column="33" TopLine="180"/>
</Position11> </Position11>
<Position12> <Position12>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="1077" Column="62" TopLine="957"/>
</Position12> </Position12>
<Position13> <Position13>
<Filename Value="..\p6502utils.pas"/> <Filename Value="..\p6502utils.pas"/>
<Caret Line="1077" Column="62" TopLine="957"/> <Caret Line="1446" Column="12" TopLine="1155"/>
</Position13> </Position13>
<Position14> <Position14>
<Filename Value="..\p6502utils.pas"/>
<Caret Line="1446" Column="12" TopLine="1155"/>
</Position14>
<Position15>
<Filename Value="..\CPUCore.pas"/> <Filename Value="..\CPUCore.pas"/>
<Caret Line="155" Column="6" TopLine="121"/> <Caret Line="155" Column="6" TopLine="121"/>
</Position14>
<Position15>
<Filename Value="..\P6502utils.pas"/>
<Caret Line="152" Column="18"/>
</Position15> </Position15>
<Position16> <Position16>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<Caret Line="152" Column="18"/> <Caret Line="19" Column="38"/>
</Position16> </Position16>
<Position17> <Position17>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<Caret Line="19" Column="38"/> <Caret Line="144" Column="26" TopLine="20"/>
</Position17> </Position17>
<Position18> <Position18>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<Caret Line="144" Column="26" TopLine="20"/> <Caret Line="201" Column="42" TopLine="180"/>
</Position18> </Position18>
<Position19> <Position19>
<Filename Value="..\P6502utils.pas"/>
<Caret Line="201" Column="42" TopLine="180"/>
</Position19>
<Position20>
<Filename Value="..\CPUCore.pas"/> <Filename Value="..\CPUCore.pas"/>
<Caret Line="88" Column="3" TopLine="71"/> <Caret Line="88" Column="3" TopLine="71"/>
</Position20> </Position19>
<Position21> <Position20>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<Caret Line="1129" Column="48" TopLine="1113"/> <Caret Line="1129" Column="48" TopLine="1113"/>
</Position20>
<Position21>
<Filename Value="..\CPUCore.pas"/>
<Caret Line="88" Column="16" TopLine="71"/>
</Position21> </Position21>
<Position22> <Position22>
<Filename Value="..\CPUCore.pas"/> <Filename Value="..\CPUCore.pas"/>
<Caret Line="88" Column="16" TopLine="71"/>
</Position22> </Position22>
<Position23> <Position23>
<Filename Value="..\CPUCore.pas"/>
</Position23>
<Position24>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<Caret Line="1129" Column="48" TopLine="1113"/> <Caret Line="1129" Column="48" TopLine="1113"/>
</Position24> </Position23>
<Position25> <Position24>
<Filename Value="..\CPUCore.pas"/> <Filename Value="..\CPUCore.pas"/>
<Caret Line="88" Column="42" TopLine="37"/> <Caret Line="88" Column="42" TopLine="37"/>
</Position25> </Position24>
<Position26> <Position25>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<Caret Line="1134" Column="7" TopLine="1115"/> <Caret Line="1134" Column="7" TopLine="1115"/>
</Position26> </Position25>
<Position27> <Position26>
<Filename Value="..\CPUCore.pas"/> <Filename Value="..\CPUCore.pas"/>
<Caret Line="64" Column="24" TopLine="37"/> <Caret Line="64" Column="24" TopLine="37"/>
</Position27> </Position26>
<Position28> <Position27>
<Filename Value="..\P6502utils.pas"/> <Filename Value="..\P6502utils.pas"/>
<Caret Line="1172" Column="12" TopLine="1150"/> <Caret Line="1172" Column="12" TopLine="1150"/>
</Position28> </Position27>
<Position29> <Position28>
<Filename Value="unit1.pas"/> <Filename Value="unit1.pas"/>
<Caret Line="131" Column="18" TopLine="113"/> <Caret Line="131" Column="18" TopLine="113"/>
</Position28>
<Position29>
<Filename Value="..\P6502utils.pas"/>
<Caret Line="234" Column="30" TopLine="211"/>
</Position29> </Position29>
<Position30>
<Filename Value="..\P6502utils.pas"/>
<Caret Line="1651" Column="5" TopLine="1620"/>
</Position30>
</JumpHistory> </JumpHistory>
<RunParams> <RunParams>
<FormatVersion Value="2"/> <FormatVersion Value="2"/>

View File

@ -539,7 +539,8 @@ Global variables used: "idIns", "modIns".
} }
var var
nemo: String; nemo: String;
opCode, par1, par2: Byte; opCode, par1: Byte;
par2: word;
begin begin
if addr>CPUMAXRAM-1 then exit(''); if addr>CPUMAXRAM-1 then exit('');
opCode := ram[addr].value; opCode := ram[addr].value;
@ -564,11 +565,19 @@ begin
aAbsolute: begin aAbsolute: begin
nBytesProc := 3; nBytesProc := 3;
if addr+2>CPUMAXRAM-1 then exit(''); if addr+2>CPUMAXRAM-1 then exit('');
par2 := ram[addr+2].value; par2 := ram[addr+2].value<<8 + par1;
Result := nemo + '$'+IntToHex(par1 + par2*256, 4); if useVarName and (ram[par2].name<>'') then begin
Result := nemo + ram[par2].name;
end else begin
Result := nemo + '$'+IntToHex(par2, 4);
end;
end; end;
aZeroPage: begin aZeroPage: begin
Result := nemo + '$'+IntToHex(par1, 2); if useVarName and (ram[par1].name<>'') then begin
Result := nemo + ram[par1].name;
end else begin
Result := nemo + '$'+IntToHex(par1, 2);
end;
nBytesProc := 2; nBytesProc := 2;
end; end;
aRelative: begin aRelative: begin
@ -633,8 +642,10 @@ Falta implementar las operaciones, cuando acceden al registro INDF, el Watchdog
los contadores, las interrupciones} los contadores, las interrupciones}
var var
opc: byte; opc: byte;
nCycles, nBytes, tmp: byte; nCycles, nBytes, tmp, off: byte;
target , addr: word; target , addr: word;
C_tmp: Boolean;
tmpRes: integer;
begin begin
//Decodifica instrucción //Decodifica instrucción
aPC := PC.W; aPC := PC.W;
@ -661,35 +672,233 @@ begin
end; end;
//Execute //Execute
case idIns of case idIns of
i_ADC:; //add with carry i_ADC: begin //add with carry
i_AND:; //and (with accumulator) if STATUS_C then begin
i_ASL:; //arithmetic shift left tmpRes := W + ram[addr].value + 1;
i_BCC:; //branch on carry clear end else begin
i_BCS:; //branch on carry set tmpRes := W + ram[addr].value;
i_BEQ:; //branch on equal (zero set) end;
i_BIT:; //bit test W := tmpRes and $FF;
i_BMI:; //branch on minus (negative set) STATUS_Z := W = 0;
i_BNE: begin STATUS_N := W > 127;
STATUS_C := tmpRes>255;
end;
i_AND: begin //and (with accumulator)
W := W and ram[addr].value;
STATUS_Z := W = 0;
STATUS_N := W > 127;
end;
i_ASL: begin //arithmetic shift left
if modIns = aAcumulat then tmp := W
else tmp := ram[addr].value;
end; //branch on not equal (zero clear) STATUS_C := (tmp and $80) <> 0; //Read bit 7
i_BPL:; //branch on plus (negative clear) tmp := tmp << 1;
i_BRK:; //break / interrupt STATUS_Z := tmp = 0;
i_BVC:; //branch on overflow clear STATUS_N := tmp > 127;
i_BVS:; //branch on overflow set
i_CLC: STATUS_C := false; //clear carry if modIns = aAcumulat then W := tmp
i_CLD: STATUS_D := false; //clear decimal else ram[addr].value := tmp;
i_CLI: STATUS_I := false; //clear interrupt disable end;
i_CLV: STATUS_V := false; //clear overflow i_BCC: begin //branch on carry clear
i_CMP:; //compare (with accumulator) if not STATUS_C then begin
i_CPX:; //compare with X off := ram[aPC+1].value;
i_CPY:; //compare with Y Inc(PC.W, nBytes); //Normal Increase PC
i_DEC:; //decrement if off>127 then begin
i_DEX:; //decrement X PC.W := (PC.W + off - 256) and $FFFF;
i_DEY:; //decrement Y end else begin
i_EOR:; //exclusive or (with accumulator) PC.W := (PC.W + off) and $FFFF;
i_INC:; //increment end;
i_INX:; //increment X //Inc(PC.W, nBytes); //No apply
i_INY:; //increment Y Inc(nClck, nCycles);
exit;
end;
end;
i_BCS: begin //branch on carry set
if STATUS_C then begin
off := ram[aPC+1].value;
Inc(PC.W, nBytes); //Normal Increase PC
if off>127 then begin
PC.w := (PC.W + off - 256) and $FFFF;
end else begin
PC.W := (PC.W + off) and $FFFF;
end;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
end;
i_BNE: begin //branch on not equal (zero clear)
if not STATUS_Z then begin
off := ram[aPC+1].value;
Inc(PC.W, nBytes); //Normal Increase PC
if off>127 then begin
PC.W := (PC.W + off - 256) and $FFFF;
end else begin
PC.W := (PC.W + off) and $FFFF;
end;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
end;
i_BEQ: begin //branch on equal (zero set)
if STATUS_Z then begin
off := ram[aPC+1].value;
Inc(PC.W, nBytes); //Normal Increase PC
if off>127 then begin
PC.w := (PC.W + off - 256) and $FFFF;
end else begin
PC.W := (PC.W + off) and $FFFF;
end;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
end;
i_BIT: begin //bit test
STATUS_N := (ram[addr].value AND $80) <> 0;
STATUS_V := (ram[addr].value AND $40) <> 0;
STATUS_Z := (W and ram[addr].value) <> 0;
end;
i_BPL: begin //branch on plus (negative clear)
if not STATUS_N then begin
off := ram[aPC+1].value;
Inc(PC.W, nBytes); //Normal Increase PC
if off>127 then begin
PC.W := (PC.W + off - 256) and $FFFF;
end else begin
PC.W := (PC.W + off) and $FFFF;
end;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
end;
i_BMI: begin //branch on minus (negative set)
if STATUS_N then begin
off := ram[aPC+1].value;
Inc(PC.W, nBytes); //Normal Increase PC
if off>127 then begin
PC.w := (PC.W + off - 256) and $FFFF;
end else begin
PC.W := (PC.W + off) and $FFFF;
end;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
end;
i_BRK: begin //break / interrupt
ram[$100 + SP].value := PC.L;
if SP = $00 then SP := $FF else dec(SP);
ram[$100 + SP].value := PC.H;
if SP = $00 then SP := $FF else dec(SP);
STATUS_I := true;
ram[$100 + SP].value := SR;
if SP = $00 then SP := $FF else dec(SP);
PC.L := ram[$FFFE].value;
PC.H := ram[$FFFF].value;
end;
i_BVC: begin //branch on overflow clear
if not STATUS_V then begin
off := ram[aPC+1].value;
Inc(PC.W, nBytes); //Normal Increase PC
if off>127 then begin
PC.W := (PC.W + off - 256) and $FFFF;
end else begin
PC.W := (PC.W + off) and $FFFF;
end;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
end;
i_BVS: begin //branch on overflow set
if STATUS_V then begin
off := ram[aPC+1].value;
Inc(PC.W, nBytes); //Normal Increase PC
if off>127 then begin
PC.w := (PC.W + off - 256) and $FFFF;
end else begin
PC.W := (PC.W + off) and $FFFF;
end;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
end;
i_CLC: STATUS_C := false; //clear carry
i_CLD: STATUS_D := false; //clear decimal
i_CLI: STATUS_I := false; //clear interrupt disable
i_CLV: STATUS_V := false; //clear overflow
i_CMP: begin //Compare (with accumulator)
tmp := ram[addr].value;
STATUS_Z := W = tmp;
STATUS_C := W >= tmp;
if W = tmp then begin
STATUS_N := false;
end else begin
STATUS_N := ((W-tmp) and $80) <> 0; //Copy bit 7
end;
end;
i_CPX: begin; //compare with X
tmp := ram[addr].value;
STATUS_Z := X = tmp;
STATUS_C := X >= tmp;
if X = tmp then begin
STATUS_N := false;
end else begin
STATUS_N := ((X-tmp) and $80) <> 0; //Copy bit 7
end;
end;
i_CPY: begin //compare with Y
tmp := ram[addr].value;
STATUS_Z := Y = tmp;
STATUS_C := Y >= tmp;
if Y = tmp then begin
STATUS_N := false;
end else begin
STATUS_N := ((Y-tmp) and $80) <> 0; //Copy bit 7
end;
end;
i_DEC: begin //decrement
tmp := (ram[addr].value - 1) and $FF;
ram[addr].value := tmp;
STATUS_Z := tmp = 0;
STATUS_N := tmp > 127;
end;
i_DEX: begin //decrement X
X := (X - 1) and $FF;
STATUS_Z := X = 0;
STATUS_N := X > 127;
end;
i_DEY: begin //decrement Y
Y := (Y - 1) and $FF;
STATUS_Z := Y = 0;
STATUS_N := Y > 127;
end;
i_EOR: begin //exclusive or (with accumulator)
W := W xor ram[addr].value;
STATUS_Z := W = 0;
STATUS_N := W > 127;
end;
i_INC: begin //increment
tmp := (ram[addr].value + 1) and $FF;
ram[addr].value := tmp;
STATUS_Z := tmp = 0;
STATUS_N := tmp > 127;
end;
i_INX: begin //increment X
X := (X + 1) and $FF;
STATUS_Z := X = 0;
STATUS_N := X > 127;
end;
i_INY: begin //increment Y
Y := (Y + 1) and $FF;
STATUS_Z := Y = 0;
STATUS_N := Y > 127;
end;
i_JMP: begin //jump i_JMP: begin //jump
case modIns of case modIns of
aAbsolute : begin aAbsolute : begin
@ -734,22 +943,81 @@ begin
STATUS_Z := Y = 0; STATUS_Z := Y = 0;
STATUS_N := Y > 127; STATUS_N := Y > 127;
end; end;
i_LSR:; //logical shift right i_LSR: begin
i_NOP:; //no operation STATUS_N := false;
i_ORA:; //or with accumulator if modIns = aAcumulat then tmp := W
else tmp := ram[addr].value;
STATUS_C := (tmp and $01) <> 0;
tmp := tmp >> 1;
STATUS_Z := tmp = 0;
if modIns = aAcumulat then W := tmp
else ram[addr].value := tmp;
end; //logical shift right
i_NOP: ; //no operation
i_ORA: begin //or with accumulator
W := W or ram[addr].value;
STATUS_Z := W = 0;
STATUS_N := W > 127;
end;
i_PHA: begin //push accumulator i_PHA: begin //push accumulator
ram[$100 + SP].value := W; ram[$100 + SP].value := W;
if SP = $00 then SP := $FF else dec(SP); if SP = $00 then SP := $FF else dec(SP);
end; end;
i_PHP:; //push processor status (SR) i_PHP: begin //push processor status (SR)
ram[$100 + SP].value := STATUS;
if SP = $00 then SP := $FF else dec(SP);
end;
i_PLA: begin //pull accumulator i_PLA: begin //pull accumulator
if SP = $FF then SP := $00 else inc(SP); if SP = $FF then SP := $00 else inc(SP);
W := ram[$100 + SP].value; W := ram[$100 + SP].value;
end; end;
i_PLP:; //pull processor status (SR) i_PLP: begin //pull processor status (SR)
i_ROL:; //rotate left if SP = $FF then SP := $00 else inc(SP);
i_ROR:; //rotate right SR := ram[$100 + SP].value;
i_RTI:; //return from interrupt end;
i_ROL: begin //rotate left
STATUS_N := false;
if modIns = aAcumulat then tmp := W
else tmp := ram[addr].value;
C_tmp := STATUS_C;
STATUS_C := (tmp and $07) <> 0; //Get bit 7
tmp := byte(tmp << 1);
if C_tmp then tmp := tmp or $01; //Insert bit 0
STATUS_Z := tmp = 0;
STATUS_N := tmp > 127;
if modIns = aAcumulat then W := tmp
else ram[addr].value := tmp;
end;
i_ROR: begin //rotate right
STATUS_N := false;
if modIns = aAcumulat then tmp := W
else tmp := ram[addr].value;
C_tmp := STATUS_C; //Save previos C
STATUS_C := (tmp and $01) <> 0; //Get bit 0
tmp := tmp >> 1;
if C_tmp then tmp := tmp or $80; //Insert bit 7
STATUS_Z := tmp = 0;
STATUS_N := tmp > 127;
if modIns = aAcumulat then W := tmp
else ram[addr].value := tmp;
end;
i_RTI: begin //return from interrupt
if SP = $FF then SP := $00 else inc(SP);
SR := ram[$100 + SP].value;
if SP = $FF then SP := $00 else inc(SP);
PC.L := ram[$100 + SP].value;
if SP = $FF then SP := $00 else inc(SP);
PC.H := ram[$100 + SP].value;
//Inc(PC.W, nBytes); //No apply
Inc(nClck, nCycles);
exit;
end;
i_RTS: begin //return from subroutine i_RTS: begin //return from subroutine
if SP = $FF then SP := $00 else inc(SP); if SP = $FF then SP := $00 else inc(SP);
PC.L := ram[$100 + SP].value; PC.L := ram[$100 + SP].value;
@ -759,7 +1027,17 @@ begin
Inc(nClck, nCycles); Inc(nClck, nCycles);
exit; exit;
end; end;
i_SBC:; //subtract with carry i_SBC: begin //subtract with carry
if STATUS_C then begin
tmpRes := W - ram[addr].value - 1;
end else begin
tmpRes := W - ram[addr].value;
end;
W := tmpRes and $FF;
STATUS_Z := W = 0;
STATUS_N := W > 127;
STATUS_C := tmpRes<0;
end;
i_SEC: STATUS_C := true; //set carry i_SEC: STATUS_C := true; //set carry
i_SED: STATUS_D := true; //set decimal i_SED: STATUS_D := true; //set decimal
i_SEI: STATUS_I := true; //set interrupt disable i_SEI: STATUS_I := true; //set interrupt disable
@ -787,260 +1065,23 @@ begin
STATUS_Z := X = 0; STATUS_Z := X = 0;
STATUS_N := X > 127; STATUS_N := X > 127;
end; end;
i_TXA:; //transfer X to accumulator i_TXA: begin //transfer X to accumulator
i_TXS:; //transfer X to stack pointer W := X;
i_TYA:; //transfer Y to accumulator STATUS_Z := W = 0;
STATUS_N := W > 127;
end;
i_TXS: begin //transfer X to stack pointer
SP := X;
end;
i_TYA: begin //transfer Y to accumulator
W := Y;
STATUS_Z := W = 0;
STATUS_N := W > 127;
end;
i_Inval: begin i_Inval: begin
MsjError := 'Invalid Opcode'; MsjError := 'Invalid Opcode';
end; end;
end; end;
{ i_ADDWF: begin
resByte := FRAM;
resWord := W + resByte;
resNib := (W and $0F) + (resByte and $0F);
if modIns = toF then begin
FRAM := resWord and $FF;
end else begin //toW
w := resWord and $FF;
end;
STATUS_Z := (resWord and $ff) = 0;
STATUS_C := (resWord > 255);
STATUS_N := (resNib > 15);
end;
i_ANDWF: begin
resByte := W and FRAM;
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte = 0;
end;
i_CLRF: begin
FRAM := 0;
STATUS_Z := true;
end;
i_CLRW: begin
W := 0;
STATUS_Z := true;
end;
i_COMF : begin
resByte := not FRAM;
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte = 0;
end;
i_DECF : begin
resByte := FRAM;
if resByte = 0 then resByte := $FF else dec(resByte);
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte = 0;
end;
i_DECFSZ: begin
resByte := FRAM;
if resByte = 0 then resByte := $FF else dec(resByte);
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte = 0;
if STATUS_Z then begin
Inc(PC.W); //Jump one instrucción
Inc(nClck); //In this case it takes one more cicle
end;
end;
i_INCF: begin
resByte := FRAM;
if resByte = 255 then resByte := 0 else inc(resByte);
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte = 0;
end;
i_INCFSZ: begin
resByte := FRAM;
if resByte = 255 then resByte := 0 else inc(resByte);
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte = 0;
if STATUS_Z then begin
Inc(PC.W); //Jump one instrucción
Inc(nClck); //In this case it takes one more cicle
end;
end;
i_IORWF: begin
resByte := W or FRAM;
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte <> 0;
end;
i_MOVF: begin
resByte := FRAM;
if modIns = toF then begin
//no mueve, solo verifica
STATUS_Z := (resByte = 0);
end else begin //toW
w := resByte;
STATUS_Z := (resByte = 0);
end;
end;
i_MOVWF: begin
FRAM := W; //escribe a donde esté mapeado, (si está mapeado)
if parIns = $02 then begin //Es el PCL
PC.H := PCLATH; //Cuando se escribe en PCL, se carga PCH con PCLATH
end;
end;
i_NOP: begin
end;
i_RLF: begin
resByte := FRAM;
bit7 := resByte and $80; //guarda bit 7
resByte := (resByte << 1) and $ff; //desplaza
//pone C en bit bajo
if STATUS_C then begin //C era 1
resByte := resByte or $01; //pone a 1 el bit 0
end else begin //C era 0
//no es necesario agregarlo, porque por defecto se agrega 0
end;
//Actualiza C
if bit7 = 0 then STATUS_C := false
else STATUS_C := true;
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
end;
i_RRF: begin
resByte := FRAM;
bit0 := resByte and $01; //guarda bit 0
resByte := resByte >> 1; //desplaza
//pone C en bit alto
if STATUS_C then begin //C era 1
resByte := resByte or $80; //pone a 1 el bit 0
end else begin //C era 0
//no es necesario agregarlo, porque por defecto se agrega 0
end;
//Actualiza C
if bit0 = 0 then STATUS_C := false
else STATUS_C := true;
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
end;
i_SUBWF: begin
resByte := FRAM;
resInt := resByte - W;
if modIns = toF then begin
FRAM := resInt and $FF;
end else begin //toW
w := resInt and $FF;
end;
STATUS_Z := (resInt = 0);
if resInt < 0 then STATUS_C := false //negativo
else STATUS_C := true;
resInt := (resByte and $0F) - (W and $0F);
if resInt < 0 then STATUS_N := false //negativo
else STATUS_N := true;
end;
i_SWAPF: begin
resByte := FRAM;
FRAM := (resByte >> 4) or (resByte << 4);
end;
i_XORWF: begin
resByte := W xor FRAM;
if modIns = toF then begin
FRAM := resByte;
end else begin //toW
w := resByte;
end;
STATUS_Z := resByte <> 0;
end;
//BIT-ORIENTED FILE REGISTER OPERATIONS
i_BCF: begin
msk := $1 << b_;
msk := not msk;
FRAM := FRAM and msk;
end;
i_BSF: begin
msk := $1 << b_;
FRAM := FRAM or msk;// b_
end;
i_BTFSC: begin
msk := $1 << b_;
if (FRAM and msk) = 0 then begin
Inc(PC.W); //Jump one instrucción
Inc(nClck); //In this case it takes one more cicle
end;
end;
i_BTFSS: begin
msk := $1 << b_;
if (FRAM and msk) <> 0 then begin
Inc(PC.W); //Jump one instrucción
Inc(nClck); //In this case it takes one more cicle
end;
end;
//LITERAL AND CONTROL OPERATIONS
i_ADDLW: begin
resWord := W + k_;
resNib := (W and $0F) + (k_ and $0F);
w := resWord and $FF;
STATUS_Z := (resWord and $ff) = 0;
STATUS_C := (resWord > 255);
STATUS_N := (resNib > 15);
end;
i_ANDLW: begin
resByte := W and K_;
w := resByte;
STATUS_Z := resByte = 0;
end;
i_IORLW: begin
resByte := W or k_;
w := resByte;
STATUS_Z := resByte <> 0;
end;
i_MOVLW: begin
W := k_;
end;
i_SUBLW: begin
resInt := k_ - W;
w := resInt and $FF;
STATUS_Z := (resInt = 0);
if resInt < 0 then STATUS_C := false //negativo
else STATUS_C := true;
resInt := (k_ and $0F) - (W and $0F);
if resInt < 0 then STATUS_N := false //negativo
else STATUS_N := true;
end;
i_XORLW: begin
resByte := W xor k_;
w := resByte;
STATUS_Z := resByte <> 0;
end;
i_Inval: begin
MsjError := 'Invalid Opcode';
end;
end;
}
//Increase counters //Increase counters
Inc(PC.W, nBytes); Inc(PC.W, nBytes);
Inc(nClck, nCycles); Inc(nClck, nCycles);