Add files via upload

This commit is contained in:
Tito Hinostroza 2022-09-16 09:20:41 -05:00 committed by GitHub
parent 88085bc91c
commit 10f727990f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 170 additions and 133 deletions

View File

@ -26,10 +26,11 @@ type
cs_unimplem //Not implemented. cs_unimplem //Not implemented.
); );
TCPURamUsed = ( TCPURamUsed = (
ruUnused, //(NOT included in PRG output file) ruUnused, //(NOT included in PRG output file).
ruCode, //Used for code (included in PRG output file) ruCodeOp, //Used for code Opcode (included in PRG output file).
ruData, //Used for variables (included in PRG output file) ruCodeDa, //Used for code Operand (included in PRG output file).
ruAbsData //Used for variables in absolute positions (NOT included in PRG output file) ruData, //Used for variables (included in PRG output file).
ruAbsData //Used for variables in absolute positions (NOT included in PRG output file).
); );
type //Models for RAM memory type //Models for RAM memory
@ -45,19 +46,19 @@ type //Models for RAM memory
Fvalue : byte; //value of the memory Fvalue : byte; //value of the memory
function Getvalue: byte; function Getvalue: byte;
procedure Setvalue(AValue: byte); procedure Setvalue(AValue: byte);
public public //General fields
name : string; //Name of the register (for variables) name : string; //Register name (for variables).
used : TCPURamUsed; //Indicates if have been written used : TCPURamUsed; //Indicates if have been written.
shared : boolean; //Used to share this register shared : boolean; //Used to share this register.
state : TCPUCellState; //Status of the cell state : TCPUCellState; //Status of the cell.
property value: byte read Getvalue write Setvalue; property value : byte read Getvalue write Setvalue;
property dvalue: byte read Fvalue write Fvalue; //Direct access to "Fvalue". property dvalue: byte read Fvalue write Fvalue; //Direct access to "Fvalue".
function Avail: boolean; //RAM implemented to use in programs function Avail : boolean; //RAM implemented to use in programs
function Free: boolean; //RAM implemented and unused function Free : boolean; //RAM implemented and unused
public //Campos para deputación public //Debugging fields
breakPnt : boolean; //Indicates if this cell have a Breakpoint breakPnt : boolean; //Indicates if this cell have a Breakpoint
{Be careful on the size of this record, because it's going to be multiplied by 64K} {Be careful on the size of this record, because it's going to be multiplied by 64K}
public //Information of position in source code. Used for debug public //Information of position in source code. Used for debug
rowSrc : word; //Row number rowSrc : word; //Row number
colSrc : word; //Column number colSrc : word; //Column number
idFile : SmallInt; //Index to a file. No load the name to save space. idFile : SmallInt; //Index to a file. No load the name to save space.
@ -65,7 +66,6 @@ type //Models for RAM memory
{Estos campos de cadena ocupan bastante espacio, aún cuado están en NULL. Si se {Estos campos de cadena ocupan bastante espacio, aún cuado están en NULL. Si se
quisiera optimizar el uso de RAM, se podría pensar en codificar, varios campos en quisiera optimizar el uso de RAM, se podría pensar en codificar, varios campos en
una sola cadena.} una sola cadena.}
topLabel : string; //Label on the top of the cell.
topComment : string; //Comment on the top of the cell. topComment : string; //Comment on the top of the cell.
sideComment: string; //Right comment to code sideComment: string; //Right comment to code
end; end;
@ -84,26 +84,26 @@ type
public //Limits public //Limits
{This variables are set just one time. So they work as constant.} {This variables are set just one time. So they work as constant.}
CPUMAXRAM: dword; //Max virtual RAM used by the CPU CPUMAXRAM: dword; //Max virtual RAM used by the CPU
public //General fields public //General fields
Model : string; //modelo de PIC Model : string; //modelo de PIC
frequen : integer; //frecuencia del reloj frequen : integer; //frecuencia del reloj
MaxFreq : integer; //Máxima frecuencia del reloj en Hz. MaxFreq : integer; //Máxima frecuencia del reloj en Hz.
//Propiedades que definen la arquitectura del CPU. //Propiedades que definen la arquitectura del CPU.
MsjError: string; MsjError: string;
public //Execution control public //Execution control
nClck : Int64; //Contador de ciclos de reloj nClck : Int64; //Contador de ciclos de reloj
CommStop: boolean; //Bandera para detener la ejecución CommStop: boolean; //Bandera para detener la ejecución
OnExecutionMsg: procedure(message: string) of object; //Genera mensaje en ejecución OnExecutionMsg: procedure(message: string) of object; //Genera mensaje en ejecución
protected //Generation of PRG files public //PRG files generation
minUsed : dword; //Dirección menor de la ROM usada minUsed : dword; //Dirección menor de la ROM usada
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; //RAM memory 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
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). Used too as flag.
dataAddr2: integer; //End address for Data variables (-1 if not used) dataAddr2: integer; //End address for Data variables (-1 if not used)
procedure ClearMemRAM; procedure ClearMemRAM;
@ -134,7 +134,7 @@ type
procedure WritePC(AValue: dword); virtual; abstract; procedure WritePC(AValue: dword); virtual; abstract;
public //Others public //Others
procedure addTopLabel(lbl: string); //Add a comment to the ASM code // procedure addTopLabel(lbl: string); //Add a comment to the ASM code
procedure addTopComm(comm: string; replace: boolean = true); //Add a comment to the ASM code procedure addTopComm(comm: string; replace: boolean = true); //Add a comment to the ASM code
procedure addSideComm(comm: string; before: boolean); //Add lateral comment to the ASM code procedure addSideComm(comm: string; before: boolean); //Add lateral comment to the ASM code
procedure addPosInformation(rowSrc, colSrc: word; idFile: byte); procedure addPosInformation(rowSrc, colSrc: word; idFile: byte);
@ -212,7 +212,7 @@ begin
ram[i].name :=''; ram[i].name :='';
ram[i].shared := false; ram[i].shared := false;
ram[i].breakPnt := false; ram[i].breakPnt := false;
ram[i].topLabel := ''; // ram[i].topLabel := '';
ram[i].sideComment:= ''; ram[i].sideComment:= '';
ram[i].topComment := ''; ram[i].topComment := '';
ram[i].idFile := -1; //Not initialized. ram[i].idFile := -1; //Not initialized.
@ -425,11 +425,11 @@ begin
if aPC>=CPUMAXRAM then exit; if aPC>=CPUMAXRAM then exit;
ram[aPC].breakPnt := not ram[aPC].breakPnt; ram[aPC].breakPnt := not ram[aPC].breakPnt;
end; end;
procedure TCPUCore.addTopLabel(lbl: string); //procedure TCPUCore.addTopLabel(lbl: string);
begin //begin
if iRam>=CPUMAXRAM then exit; // if iRam>=CPUMAXRAM then exit;
ram[iRam].topLabel := lbl; // ram[iRam].topLabel := lbl;
end; //end;
procedure TCPUCore.addTopComm(comm: string; replace: boolean); procedure TCPUCore.addTopComm(comm: string; replace: boolean);
{Agrega un comentario de línea al código en la posición de memoria actual} {Agrega un comentario de línea al código en la posición de memoria actual}
begin begin

View File

@ -1,3 +1,7 @@
16/09/2022: Se coorige ejecución de instrucción SBC.
16/09/2022: Se separa el tipo ruCode en dos tipos ruCodeOp y ruCodeDa.
16/09/2022: Se agrega protección a desborde en la instrucción i_ASL.
0.5 0.5
=== ===
04/09/2020: Se mueve el método FindOpcode() fuera del objeto TP6502Instruct. 04/09/2020: Se mueve el método FindOpcode() fuera del objeto TP6502Instruct.

View File

@ -201,8 +201,10 @@ type
function ValidRAMaddr(addr: word): boolean; //indica si una posición de memoria es válida function ValidRAMaddr(addr: word): boolean; //indica si una posición de memoria es válida
public //Methods to code instructions according to syntax public //Methods to code instructions according to syntax
disableCodegen: boolean; //Flag to disable the Code generation. disableCodegen: boolean; //Flag to disable the Code generation.
procedure useRAMCode; procedure useRAMCodeOp;
procedure useRAMCodeDa;
procedure codByte(const value: byte; isData: boolean); procedure codByte(const value: byte; isData: boolean);
procedure codByte(const value: byte; used: TCPURamUsed; name: string = '');
procedure codAsm(const inst: TP6502Inst; addMode: TP6502AddMode; param: word); procedure codAsm(const inst: TP6502Inst; addMode: TP6502AddMode; param: word);
procedure cod_JMP_at(iRam0: integer; const k: word); procedure cod_JMP_at(iRam0: integer; const k: word);
procedure cod_REL_JMP_at(iRam0: integer; const k: word); procedure cod_REL_JMP_at(iRam0: integer; const k: word);
@ -210,6 +212,8 @@ type
public //Aditional methods public //Aditional methods
function IsRelJump(idInst: TP6502Inst): boolean; //Idnetify realtive jumps Opcodes function IsRelJump(idInst: TP6502Inst): boolean; //Idnetify realtive jumps Opcodes
procedure GenHex(hexFile: string; startAddr: integer = - 1); //genera un archivo hex procedure GenHex(hexFile: string; startAddr: integer = - 1); //genera un archivo hex
function GetASMlineAt(addr: word; incAdrr, incValues, incCom,
incVarNam: boolean; out nBytes: byte): string;
procedure DumpCodeAsm(lOut: TStrings; incAdrr, incValues, incCom, procedure DumpCodeAsm(lOut: TStrings; incAdrr, incValues, incCom,
incVarNam: boolean); incVarNam: boolean);
public //Initialization public //Initialization
@ -283,10 +287,15 @@ begin
exit(false); exit(false);
end; end;
{ TP6502 } { TP6502 }
procedure TP6502.useRAMCode; procedure TP6502.useRAMCodeOp;
{Set current position as used and increase the index iRam. If error;update "MsjError"} {Set current position as used and increase the index iRam. If error;update "MsjError"}
begin begin
ram[iRam].used := ruCode; //Mark as used. ram[iRam].used := ruCodeOp; //Mark as used.
inc(iRam);
end;
procedure TP6502.useRAMCodeDa;
begin
ram[iRam].used := ruCodeDa; //Mark as used.
inc(iRam); inc(iRam);
end; end;
procedure TP6502.codByte(const value: byte; isData: boolean); procedure TP6502.codByte(const value: byte; isData: boolean);
@ -301,6 +310,18 @@ begin
ram[iRam].used := ruData; //Mark as used. ram[iRam].used := ruData; //Mark as used.
inc(iRam); inc(iRam);
end; end;
procedure TP6502.codByte(const value: byte; used: TCPURamUsed; name: string = '');
{Write a byte to the RAM memory.}
begin
if iRam >= CPUMAXRAM then begin
MsjError := 'RAM Memory limit exceeded.';
exit;
end;
ram[iRam].value := value;
ram[iRam].used := used; //Mark as used.
if name<>'' then ram[iRam].name := name;
inc(iRam);
end;
procedure TP6502.codAsm(const inst: TP6502Inst; addMode: TP6502AddMode; param: word); procedure TP6502.codAsm(const inst: TP6502Inst; addMode: TP6502AddMode; param: word);
{General routine to codify assembler instructions.} {General routine to codify assembler instructions.}
var var
@ -319,7 +340,7 @@ begin
exit; exit;
end; end;
ram[iRam].value := rInst.instrInform[addMode].Opcode; ram[iRam].value := rInst.instrInform[addMode].Opcode;
useRAMCode; //Set as used and increase index. useRAMCodeOp; //Set as used and increase index.
//Encode parameters //Encode parameters
case addMode of case addMode of
aImplicit: begin aImplicit: begin
@ -345,55 +366,55 @@ begin
MsjError:= 'Invalid Address Mode (Immediate)'; MsjError:= 'Invalid Address Mode (Immediate)';
end; end;
ram[iRam].value := lo(param); //escribe parámetro ram[iRam].value := lo(param); //escribe parámetro
useRAMCode; useRAMCodeDa;
end; end;
aAbsolute:begin aAbsolute:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
ram[iRam].value := hi(param); ram[iRam].value := hi(param);
useRAMCode; useRAMCodeDa;
end; end;
aZeroPage:begin aZeroPage:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
end; end;
aRelative:begin aRelative:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
end; end;
aIndirect:begin aIndirect:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
ram[iRam].value := hi(param); ram[iRam].value := hi(param);
useRAMCode; useRAMCodeDa;
end; end;
aAbsolutX:begin aAbsolutX:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
ram[iRam].value := hi(param); ram[iRam].value := hi(param);
useRAMCode; useRAMCodeDa;
end; end;
aAbsolutY:begin aAbsolutY:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
ram[iRam].value := hi(param); ram[iRam].value := hi(param);
useRAMCode; useRAMCodeDa;
end; end;
aZeroPagX:begin aZeroPagX:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
end; end;
aZeroPagY:begin aZeroPagY:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
end; end;
aIndirecX:begin aIndirecX:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
end; end;
aIndirecY:begin aIndirecY:begin
ram[iRam].value := lo(param); ram[iRam].value := lo(param);
useRAMCode; useRAMCodeDa;
end; end;
else else
raise Exception.Create('Implementation Error.'); raise Exception.Create('Implementation Error.');
@ -644,7 +665,7 @@ 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, off: byte; nCycles, nBytes, tmp, off, OP1, OP2: byte;
target , addr: word; target , addr: word;
C_tmp: Boolean; C_tmp: Boolean;
tmpRes: integer; tmpRes: integer;
@ -675,15 +696,18 @@ begin
//Execute //Execute
case idIns of case idIns of
i_ADC: begin //add with carry i_ADC: begin //add with carry
OP1 := W; //Keep operand.
OP2 := ram[addr].value;
if STATUS_C then begin if STATUS_C then begin
tmpRes := W + ram[addr].value + 1; tmpRes := W + OP2 + 1;
end else begin end else begin
tmpRes := W + ram[addr].value; tmpRes := W + OP2;
end; end;
W := tmpRes and $FF; W := tmpRes and $FF;
STATUS_Z := W = 0; STATUS_Z := W = 0;
STATUS_N := W > 127; STATUS_N := W > 127;
STATUS_C := tmpRes>255; STATUS_C := tmpRes>255;
STATUS_V := ((OP1 XOR W) AND (OP2 XOR W) AND $80)<>0; //Based on: http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html
end; end;
i_AND: begin //and (with accumulator) i_AND: begin //and (with accumulator)
W := W and ram[addr].value; W := W and ram[addr].value;
@ -695,7 +719,7 @@ begin
else tmp := ram[addr].value; else tmp := ram[addr].value;
STATUS_C := (tmp and $80) <> 0; //Read bit 7 STATUS_C := (tmp and $80) <> 0; //Read bit 7
tmp := tmp << 1; tmp := (tmp << 1) and $FF;
STATUS_Z := tmp = 0; STATUS_Z := tmp = 0;
STATUS_N := tmp > 127; STATUS_N := tmp > 127;
@ -711,8 +735,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -725,8 +748,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -739,8 +761,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -753,8 +774,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -772,8 +792,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -786,8 +805,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -811,8 +829,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -825,8 +842,7 @@ begin
end else begin end else begin
PC.W := (PC.W + off) and $FFFF; PC.W := (PC.W + off) and $FFFF;
end; end;
//Inc(PC.W, nBytes); //No apply Inc(nClck, nCycles + 1); //Extra cycle in branch
Inc(nClck, nCycles);
exit; exit;
end; end;
end; end;
@ -918,7 +934,7 @@ begin
exit; exit;
end; end;
i_JSR: begin i_JSR: begin
inc(PC.W, 3); //Next psoition inc(PC.W, 3); //Next position
//Save return //Save return
ram[$100 + SP].value := PC.H; ram[$100 + SP].value := PC.H;
if SP = $00 then SP := $FF else dec(SP); if SP = $00 then SP := $FF else dec(SP);
@ -930,17 +946,17 @@ begin
Inc(nClck, nCycles); Inc(nClck, nCycles);
exit; exit;
end; //jump subroutine end; //jump subroutine
i_LDA: begin //load accumulator i_LDA: begin //Load accumulator
W := ram[addr].value; W := ram[addr].value;
STATUS_Z := W = 0; STATUS_Z := W = 0;
STATUS_N := W > 127; STATUS_N := W > 127;
end; end;
i_LDX: begin //load X i_LDX: begin //Load X
X := ram[addr].value; X := ram[addr].value;
STATUS_Z := X = 0; STATUS_Z := X = 0;
STATUS_N := X > 127; STATUS_N := X > 127;
end; end;
i_LDY: begin //load y i_LDY: begin //Load y
Y := ram[addr].value; Y := ram[addr].value;
STATUS_Z := Y = 0; STATUS_Z := Y = 0;
STATUS_N := Y > 127; STATUS_N := Y > 127;
@ -958,28 +974,28 @@ begin
else ram[addr].value := tmp; else ram[addr].value := tmp;
end; //logical shift right end; //logical shift right
i_NOP: ; //no operation i_NOP: ; //no operation
i_ORA: begin //or with accumulator i_ORA: begin //Or with accumulator
W := W or ram[addr].value; W := W or ram[addr].value;
STATUS_Z := W = 0; STATUS_Z := W = 0;
STATUS_N := W > 127; STATUS_N := W > 127;
end; 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: begin //push processor status (SR) i_PHP: begin //Push processor status (SR)
ram[$100 + SP].value := STATUS; ram[$100 + SP].value := STATUS;
if SP = $00 then SP := $FF else dec(SP); if SP = $00 then SP := $FF else dec(SP);
end; 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: begin //pull processor status (SR) i_PLP: begin //Pull processor status (SR)
if SP = $FF then SP := $00 else inc(SP); if SP = $FF then SP := $00 else inc(SP);
SR := ram[$100 + SP].value; SR := ram[$100 + SP].value;
end; end;
i_ROL: begin //rotate left i_ROL: begin //Rotate left
STATUS_N := false; STATUS_N := false;
if modIns = aAcumulat then tmp := W if modIns = aAcumulat then tmp := W
else tmp := ram[addr].value; else tmp := ram[addr].value;
@ -994,7 +1010,7 @@ begin
if modIns = aAcumulat then W := tmp if modIns = aAcumulat then W := tmp
else ram[addr].value := tmp; else ram[addr].value := tmp;
end; end;
i_ROR: begin //rotate right i_ROR: begin //Rotate right
STATUS_N := false; STATUS_N := false;
if modIns = aAcumulat then tmp := W if modIns = aAcumulat then tmp := W
else tmp := ram[addr].value; else tmp := ram[addr].value;
@ -1009,7 +1025,7 @@ begin
if modIns = aAcumulat then W := tmp if modIns = aAcumulat then W := tmp
else ram[addr].value := tmp; else ram[addr].value := tmp;
end; end;
i_RTI: begin //return from interrupt i_RTI: begin //Return from interrupt
if SP = $FF then SP := $00 else inc(SP); if SP = $FF then SP := $00 else inc(SP);
SR := ram[$100 + SP].value; SR := ram[$100 + SP].value;
if SP = $FF then SP := $00 else inc(SP); if SP = $FF then SP := $00 else inc(SP);
@ -1020,7 +1036,7 @@ begin
Inc(nClck, nCycles); Inc(nClck, nCycles);
exit; exit;
end; 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;
if SP = $FF then SP := $00 else inc(SP); if SP = $FF then SP := $00 else inc(SP);
@ -1029,16 +1045,19 @@ begin
Inc(nClck, nCycles); Inc(nClck, nCycles);
exit; exit;
end; end;
i_SBC: begin //subtract with carry i_SBC: begin //Subtract with carry
OP1 := W; //Keep operand.
OP2 := ram[addr].value;
if STATUS_C then begin if STATUS_C then begin
tmpRes := W - ram[addr].value - 1; tmpRes := W - OP2;
end else begin end else begin
tmpRes := W - ram[addr].value; tmpRes := W - OP2 - 1;
end; end;
W := tmpRes and $FF; W := tmpRes and $FF;
STATUS_Z := W = 0; STATUS_Z := W = 0;
STATUS_N := W > 127; STATUS_N := W > 127;
STATUS_C := tmpRes<0; STATUS_C := not (tmpRes<0);
STATUS_V := ((OP1 XOR W) AND (OP2 XOR W) AND $80)<>0; //Based on: http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html
end; 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
@ -1093,6 +1112,11 @@ procedure TP6502.ExecTo(endAdd: word);
contador del programa, sea igual a la dirección "endAdd".} contador del programa, sea igual a la dirección "endAdd".}
begin begin
//Hace una primera ejecución, sin verificar Breakpoints //Hace una primera ejecución, sin verificar Breakpoints
if ram[PC.W].used = ruUnused then begin
//Encontró un BreakPoint, sale sin ejecutar esa instrucción
if OnExecutionMsg<>nil then OnExecutionMsg('Stopped. Unused RAM location.');
exit;
end;
Exec(PC.W); Exec(PC.W);
//Ejecuta cíclicamnente //Ejecuta cíclicamnente
while PC.W <> endAdd do begin while PC.W <> endAdd do begin
@ -1101,6 +1125,11 @@ begin
if OnExecutionMsg<>nil then OnExecutionMsg('Stopped for breakpoint.'); if OnExecutionMsg<>nil then OnExecutionMsg('Stopped for breakpoint.');
exit; exit;
end; end;
if ram[PC.W].used = ruUnused then begin
//Encontró un BreakPoint, sale sin ejecutar esa instrucción
if OnExecutionMsg<>nil then OnExecutionMsg('Stopped. Unused RAM location.');
exit;
end;
//Ejecuta //Ejecuta
Exec(PC.W); Exec(PC.W);
//Debe haber una forma de salir si es un lazo infinito //Debe haber una forma de salir si es un lazo infinito
@ -1298,13 +1327,48 @@ begin
if addr > CPUMAXRAM then exit(false); //excede límite if addr > CPUMAXRAM then exit(false); //excede límite
exit(true); exit(true);
end; end;
function TP6502.GetASMlineAt(addr: word;
incAdrr, incValues, incCom, incVarNam: boolean; out nBytes: byte): string;
{Returns a line of text with an ASM instruction.}
var
opCode, comLat: string;
begin
comLat := ram[addr].sideComment;
//Decodifica instrucción
opCode := DisassemblerAt(addr, nBytes, incVarNam); //Instrucción
//Verificas si incluye dirección física
Result := '';
if incAdrr then begin
//Agrega dirección al inicio
Result := '$'+IntToHex(addr,4) + ' ';
end;
if incValues then begin
//Agrega bytes después
if nBytes = 1 then begin
Result := Result + IntToHex(ram[addr].value, 2) + ' ' ;
end else if nBytes = 2 then begin
Result := Result + IntToHex(ram[addr].value, 2) + ' ' +
IntToHex(ram[addr+1].value, 2) + ' ';
end else if nBytes = 3 then begin
Result := Result + IntToHex(ram[addr].value, 2) + ' ' +
IntToHex(ram[addr+1].value, 2) + ' ' +
IntToHex(ram[addr+2].value, 2) + ' ';
end;
end;
Result := Result + opCode;
//Check if there is lateral comment
if incCom then begin
Result := Result + ' ' + comLat;
end;
end;
procedure TP6502.DumpCodeAsm(lOut: TStrings; procedure TP6502.DumpCodeAsm(lOut: TStrings;
incAdrr, incValues, incCom, incVarNam: boolean); incAdrr, incValues, incCom, incVarNam: boolean);
{Desensambla las instrucciones grabadas en el PIC. {Desensambla las instrucciones grabadas en el PIC.
Se debe llamar despues de llamar a GenHex(), para que se actualicen las variables} Se debe llamar despues de llamar a GenHex(), para que se actualicen las variables
minUsed y maxUsed.}
var var
i: Word; i: Word;
lblLin, comLat, comLin, lin, opCode: String; lblLin, comLin, lin: String;
nBytes: byte; nBytes: byte;
const const
SPACEPAD = ' '; SPACEPAD = ' ';
@ -1317,59 +1381,31 @@ begin
end; end;
i := minUsed; i := minUsed;
while i <= maxUsed do begin while i <= maxUsed do begin
//Lee comentarios y etiqueta //Read label and comments.
lblLin := ram[i].topLabel; lblLin := ram[i].name;
comLat := ram[i].sideComment;
comLin := ram[i].topComment; comLin := ram[i].topComment;
//Verifica si es variable //Check RAM position.
if ram[i].used in [ruData, ruAbsData] then begin if ram[i].used in [ruData, ruAbsData] then begin
//Escribe en forma de variable //Must be a variable.
if incAdrr then begin if incAdrr then begin
if comLin<>'' then lOut.add(comLin); if comLin<>'' then lOut.add(comLin);
//lOut.Add( PadRight(ram[i].name, Length(SPACEPAD)) + '$'+IntToHex(i,4) + ' DB ??'); lOut.Add( PadRight(lblLin, Length(SPACEPAD)) + '$'+IntToHex(i,4) + ' DB ' +
lOut.Add( PadRight(ram[i].name, Length(SPACEPAD)) + '$'+IntToHex(i,4) + ' DB ' +
IntToHEx(ram[i].value,2) ); IntToHEx(ram[i].value,2) );
end else begin end else begin
//lOut.Add( PadRight(ram[i].name, Length(SPACEPAD)) + 'DB ??'); lOut.Add( PadRight(lblLin, Length(SPACEPAD)) + 'DB ' + IntToHEx(ram[i].value,2) );
lOut.Add( PadRight(ram[i].name, Length(SPACEPAD)) + 'DB ' + IntToHEx(ram[i].value,2) );
end; end;
i := i + 1; i := i + 1;
continue; end else begin
end; //Debe ser código o memoria sin usar.
//Escribe etiqueta al inicio de línea if lblLin<>'' then lOut.Add(lblLin+':'); //Etiqueta al inicio de línea
if lblLin<>'' then lOut.Add(lblLin+':'); //Escribe comentario al inicio de línea
//Escribe comentario al inicio de línea if incCom and (comLin<>'') then begin
if incCom and (comLin<>'') then begin lOut.Add(comLin);
lOut.Add(comLin);
end;
//Decodifica instrucción
opCode := DisassemblerAt(i, nBytes, incVarNam); //Instrucción
//Verificas si incluye dirección física
lin := '';
if incAdrr then begin
//Agrega dirección al inicio
lin := '$'+IntToHex(i,4) + ' ';
end;
if incValues then begin
//Agrega bytes después
if nBytes = 1 then begin
lin := lin + IntToHex(ram[i].value, 2) + ' ' ;
end else if nBytes = 2 then begin
lin := lin + IntToHex(ram[i].value, 2) + ' ' +
IntToHex(ram[i+1].value, 2) + ' ';
end else if nBytes = 3 then begin
lin := lin + IntToHex(ram[i].value, 2) + ' ' +
IntToHex(ram[i+1].value, 2) + ' ' +
IntToHex(ram[i+2].value, 2) + ' ';
end; end;
lin := GetASMlineAt(i, incAdrr, incValues, incCom, incVarNam, nBytes);
lOut.Add(SPACEPAD + lin);
i := i + nBytes; //Incrementa a siguiente instrucción
end; end;
lin := lin + opCode;
//Verifica si incluye comentario lateral
if incCom then begin
lin := lin + ' ' + comLat;
end;
lOut.Add(SPACEPAD + lin);
i := i + nBytes; //Incrementa a siguiente instrucción
end; end;
end; end;
procedure TP6502.GenHex(hexFile: string; startAddr: integer = -1); procedure TP6502.GenHex(hexFile: string; startAddr: integer = -1);
@ -1386,7 +1422,7 @@ begin
maxUsed := 0; maxUsed := 0;
for i := 0 to CPUMAXRAM-1 do begin for i := 0 to CPUMAXRAM-1 do begin
//if ram[i].used in [ruCode, ruData] then begin //Changed in versión 0.7.1 //if ram[i].used in [ruCode, ruData] then begin //Changed in versión 0.7.1
if ram[i].used in [ruCode] then begin if ram[i].used in [ruCodeOp, ruCodeDa] then begin
if i<minUsed then minUsed := i; if i<minUsed then minUsed := i;
if i>maxUsed then maxUsed := i; if i>maxUsed then maxUsed := i;
end; end;
@ -1397,7 +1433,7 @@ begin
maxUsed := 0; maxUsed := 0;
for i := minUsed to CPUMAXRAM-1 do begin for i := minUsed to CPUMAXRAM-1 do begin
//if ram[i].used in [ruCode, ruData] then begin //Changed in versión 0.7.1 //if ram[i].used in [ruCode, ruData] then begin //Changed in versión 0.7.1
if ram[i].used in [ruCode] then begin if ram[i].used in [ruCodeOp, ruCodeDa] then begin
if i>maxUsed then maxUsed := i; if i>maxUsed then maxUsed := i;
end; end;
end; end;
@ -1431,9 +1467,6 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure InitTables; procedure InitTables;
var
i : TP6502Inst;
j : TP6502AddMode;
begin begin
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
////////////////// Set instructions information /////////////////// ////////////////// Set instructions information ///////////////////