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:
parent
42cc492390
commit
a662de2961
16
CPUCore.pas
16
CPUCore.pas
|
@ -60,14 +60,13 @@ type //Models for RAM memory
|
||||||
function Getvalue: byte;
|
function Getvalue: byte;
|
||||||
procedure Setvalue(AValue: byte);
|
procedure Setvalue(AValue: byte);
|
||||||
public
|
public
|
||||||
addr : word; //dirección física de memoria, en donde está la celda.
|
|
||||||
name : string; //Name of the register (for variables)
|
name : string; //Name of the register (for variables)
|
||||||
used : boolean; //Indicates if have been written
|
used : boolean; //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 AvailGPR: boolean;
|
function Avail: boolean;
|
||||||
public //Campos para deputación
|
public //Campos para deputación
|
||||||
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}
|
||||||
|
@ -94,7 +93,7 @@ type
|
||||||
TCPUCore = class
|
TCPUCore = class
|
||||||
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 : word; //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
|
||||||
|
@ -106,8 +105,8 @@ type
|
||||||
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 HEX files
|
protected //Generation of HEX files
|
||||||
minUsed : word; //Dirección menor de la ROM usada
|
minUsed : dword; //Dirección menor de la ROM usada
|
||||||
maxUsed : word; //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; //memoria RAM
|
||||||
|
@ -144,7 +143,7 @@ type
|
||||||
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; //Ejecuta hasta cierta dirección
|
||||||
procedure Reset; 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;
|
||||||
public //Others
|
public //Others
|
||||||
|
@ -168,7 +167,7 @@ procedure TCPURamCell.Setvalue(AValue: byte);
|
||||||
begin
|
begin
|
||||||
Fvalue := AValue;
|
Fvalue := AValue;
|
||||||
end;
|
end;
|
||||||
function TCPURamCell.AvailGPR: boolean;
|
function TCPURamCell.Avail: boolean;
|
||||||
{Indica si el registro es una dirección disponible en la memoria RAM.}
|
{Indica si el registro es una dirección disponible en la memoria RAM.}
|
||||||
begin
|
begin
|
||||||
Result := (state = cs_impleGPR);
|
Result := (state = cs_impleGPR);
|
||||||
|
@ -211,7 +210,6 @@ var
|
||||||
i: word;
|
i: word;
|
||||||
begin
|
begin
|
||||||
for i:=0 to high(ram) do begin
|
for i:=0 to high(ram) do begin
|
||||||
ram[i].addr := i;
|
|
||||||
ram[i].state := cs_unimplem;
|
ram[i].state := cs_unimplem;
|
||||||
end;
|
end;
|
||||||
//Inicia estado de pines
|
//Inicia estado de pines
|
||||||
|
@ -542,7 +540,7 @@ end;
|
||||||
constructor TCPUCore.Create;
|
constructor TCPUCore.Create;
|
||||||
begin
|
begin
|
||||||
hexLines := TStringList.Create;
|
hexLines := TStringList.Create;
|
||||||
frequen := 4000000; //4MHz
|
frequen := 1000000; //4MHz
|
||||||
end;
|
end;
|
||||||
destructor TCPUCore.Destroy;
|
destructor TCPUCore.Destroy;
|
||||||
begin
|
begin
|
||||||
|
|
297
P6502utils.pas
297
P6502utils.pas
|
@ -167,8 +167,7 @@ type
|
||||||
W : byte; //Registro de trabajo
|
W : byte; //Registro de trabajo
|
||||||
PC : TWordRec; //PC as record to fast access for bytes
|
PC : TWordRec; //PC as record to fast access for bytes
|
||||||
PCLATH : byte; //Contador de Programa H
|
PCLATH : byte; //Contador de Programa H
|
||||||
STKPTR : 0..7; //Puntero de pila
|
SP : byte; //Puntero de pila
|
||||||
STACK : array[0..7] of word;
|
|
||||||
property STATUS: byte read GetSTATUS;
|
property STATUS: byte read GetSTATUS;
|
||||||
property STATUS_Z: boolean read GetSTATUS_Z write SetSTATUS_Z;
|
property STATUS_Z: boolean read GetSTATUS_Z write SetSTATUS_Z;
|
||||||
property STATUS_C: boolean read GetSTATUS_C write SetSTATUS_C;
|
property STATUS_C: boolean read GetSTATUS_C write SetSTATUS_C;
|
||||||
|
@ -184,32 +183,31 @@ type
|
||||||
procedure ExecTo(endAdd: word); override; //Ejecuta hasta cierta dirección
|
procedure ExecTo(endAdd: word); override; //Ejecuta hasta cierta dirección
|
||||||
procedure ExecStep; override; //Execute one instruction considering CALL as one instruction
|
procedure ExecStep; override; //Execute one instruction considering CALL as one instruction
|
||||||
procedure ExecNCycles(nCyc: integer; out stopped: boolean); override; //Ejecuta hasta cierta dirección
|
procedure ExecNCycles(nCyc: integer; out stopped: boolean); override; //Ejecuta hasta cierta dirección
|
||||||
procedure Reset; override;
|
procedure Reset(hard: boolean); override;
|
||||||
function ReadPC: dword; override;
|
function ReadPC: dword; override;
|
||||||
procedure WritePC(AValue: dword); override;
|
procedure WritePC(AValue: dword); override;
|
||||||
public //Memories
|
public //Memories
|
||||||
procedure Decode(const opCode: word); //decodifica instrucción
|
procedure Decode(const opCode: word); //Decode instruction.
|
||||||
function Disassembler(const opCode, par1, par2: byte; out nBytesProc: byte;
|
|
||||||
useVarName: boolean=false): string; //Desensambla la instrucción actual
|
|
||||||
function DisassemblerAt(addr: word; out nBytesProc: byte; useVarName: boolean
|
function DisassemblerAt(addr: word; out nBytesProc: byte; useVarName: boolean
|
||||||
): string; override;
|
): string; override;
|
||||||
public //Funciones para la memoria RAM
|
public //RAM memory functions
|
||||||
function GetFreeByte(out addr: word; shared: boolean): boolean;
|
function GetFreeByte(out addr: word; shared: boolean): boolean;
|
||||||
function GetFreeBytes(const size: integer; var addr: word): boolean; //obtiene una dirección libre
|
function GetFreeBytes(const size: integer; var addr: word): boolean; //obtiene una dirección libre
|
||||||
function TotalMemRAM: word; //devuelve el total de memoria RAM
|
function TotalMemRAM: integer; //devuelve el total de memoria RAM
|
||||||
function UsedMemRAM: word; //devuelve el total de memoria RAM usada
|
function UsedMemRAM: word; //devuelve el total de memoria RAM usada
|
||||||
procedure ExploreUsed(rutExplorRAM: TCPURutExplorRAM); //devuelve un reporte del uso de la RAM
|
procedure ExploreUsed(rutExplorRAM: TCPURutExplorRAM); //devuelve un reporte del uso de la RAM
|
||||||
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 //Métodos para codificar instrucciones de acuerdo a la sintaxis
|
public //Métthods to code instructions according to syntax
|
||||||
procedure useRAM;
|
procedure useRAM;
|
||||||
procedure codAsmFD(const inst: TP6502Inst; addMode: TP6502AddMode; param: word);
|
procedure codAsm(const inst: TP6502Inst; addMode: TP6502AddMode; param: word);
|
||||||
procedure codGotoAt(iRam0: integer; const k: word);
|
procedure codGotoAt(iRam0: integer; const k: word);
|
||||||
procedure codCallAt(iRam0: integer; const k: word);
|
procedure codCallAt(iRam0: integer; const k: word);
|
||||||
function codInsert(iRam0, nInsert, nWords: integer): boolean;
|
function codInsert(iRam0, nInsert, nWords: integer): boolean;
|
||||||
public //Métodos adicionales
|
public //Adicional methods
|
||||||
function FindOpcode(Op: string): TP6502Inst; //busca Opcode
|
function FindOpcode(Op: string): TP6502Inst; //busca Opcode
|
||||||
procedure GenHex(hexFile: string; ConfigWord: integer = - 1); //genera un archivo hex
|
procedure GenHex(hexFile: string); //genera un archivo hex
|
||||||
procedure DumpCode(lOut: TStrings; incAdrr, incCom, incVarNam: boolean); //vuelva en código que contiene
|
procedure DumpCodeAsm(lOut: TStrings; incAdrr, incValues, incCom,
|
||||||
|
incVarNam: boolean);
|
||||||
public //Initialization
|
public //Initialization
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
@ -254,20 +252,20 @@ procedure TP6502.useRAM;
|
||||||
{Marca la posición actual, como usada, e incrementa el puntero iRam. Si hay error,
|
{Marca la posición actual, como usada, e incrementa el puntero iRam. Si hay error,
|
||||||
actualiza el campo "MsjError"}
|
actualiza el campo "MsjError"}
|
||||||
begin
|
begin
|
||||||
//Protección de desborde
|
|
||||||
if iRam >= CPUMAXRAM then begin
|
|
||||||
MsjError := 'RAM Memory limit exceeded.';
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
ram[iRam].used := true; //marca como usado
|
ram[iRam].used := true; //marca como usado
|
||||||
inc(iRam);
|
inc(iRam);
|
||||||
end;
|
end;
|
||||||
procedure TP6502.codAsmFD(const inst: TP6502Inst; addMode: TP6502AddMode; param: word);
|
procedure TP6502.codAsm(const inst: TP6502Inst; addMode: TP6502AddMode; param: word);
|
||||||
{Codifica las instrucciones orientadas a registro, con sintAxis: NEMÓNICO f,d}
|
{Rutina general para codificar instrucciones en ensamblador}
|
||||||
var
|
var
|
||||||
rInst: TP6502Instruct;
|
rInst: TP6502Instruct;
|
||||||
begin
|
begin
|
||||||
rInst := PIC16InstName[inst];
|
rInst := PIC16InstName[inst];
|
||||||
|
//Overflow protection
|
||||||
|
if iRam >= CPUMAXRAM then begin
|
||||||
|
MsjError := 'RAM Memory limit exceeded.';
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
//Write OpCode
|
//Write OpCode
|
||||||
ram[iRam].value := rInst.instrInform[addMode].Opcode;
|
ram[iRam].value := rInst.instrInform[addMode].Opcode;
|
||||||
useRAM; //marca como usado e incrementa puntero.
|
useRAM; //marca como usado e incrementa puntero.
|
||||||
|
@ -350,7 +348,6 @@ begin
|
||||||
raise Exception.Create('Implementation Error.');
|
raise Exception.Create('Implementation Error.');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TP6502.codGotoAt(iRam0: integer; const k: word);
|
procedure TP6502.codGotoAt(iRam0: integer; const k: word);
|
||||||
{Codifica una instrucción GOTO, en una posición específica y sin alterar el puntero "iFlash"
|
{Codifica una instrucción GOTO, en una posición específica y sin alterar el puntero "iFlash"
|
||||||
actual. Se usa para completar saltos indefinidos}
|
actual. Se usa para completar saltos indefinidos}
|
||||||
|
@ -362,7 +359,6 @@ begin
|
||||||
ram[iRam0+1].value := lo(k);
|
ram[iRam0+1].value := lo(k);
|
||||||
ram[iRam0+2].value := hi(k);
|
ram[iRam0+2].value := hi(k);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TP6502.codCallAt(iRam0: integer; const k: word);
|
procedure TP6502.codCallAt(iRam0: integer; const k: word);
|
||||||
{Codifica una instrucción i_CALL, en una posición específica y sin alterar el puntero "iFlash"
|
{Codifica una instrucción i_CALL, en una posición específica y sin alterar el puntero "iFlash"
|
||||||
actual. Se usa para completar llamadas indefinidas}
|
actual. Se usa para completar llamadas indefinidas}
|
||||||
|
@ -372,7 +368,6 @@ begin
|
||||||
rInst := PIC16InstName[i_JSR];
|
rInst := PIC16InstName[i_JSR];
|
||||||
ram[iRam0].value := rInst.instrInform[aAbsolute].Opcode;
|
ram[iRam0].value := rInst.instrInform[aAbsolute].Opcode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TP6502.codInsert(iRam0, nInsert, nWords: integer): boolean;
|
function TP6502.codInsert(iRam0, nInsert, nWords: integer): boolean;
|
||||||
{Inserta en la posición iRam0, "nInsert" palabras, desplazando "nWords" palabras.
|
{Inserta en la posición iRam0, "nInsert" palabras, desplazando "nWords" palabras.
|
||||||
Al final debe quedar "nInsert" palabras de espacio libre en iRam0.
|
Al final debe quedar "nInsert" palabras de espacio libre en iRam0.
|
||||||
|
@ -482,6 +477,7 @@ procedure TP6502.Decode(const opCode: word);
|
||||||
{Decode the value of "opCode" and update:
|
{Decode the value of "opCode" and update:
|
||||||
* "idIns" -> Instruction ID
|
* "idIns" -> Instruction ID
|
||||||
* "modIns" -> Address Mode
|
* "modIns" -> Address Mode
|
||||||
|
If not found, returns "i_Inval" in "idIns".
|
||||||
}
|
}
|
||||||
var
|
var
|
||||||
i : TP6502Inst;
|
i : TP6502Inst;
|
||||||
|
@ -497,91 +493,103 @@ begin
|
||||||
if iInfom.Opcode = opCode then begin
|
if iInfom.Opcode = opCode then begin
|
||||||
idIns := i;
|
idIns := i;
|
||||||
modIns := j;
|
modIns := j;
|
||||||
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
//Not found
|
||||||
|
idIns := i_Inval;
|
||||||
end;
|
end;
|
||||||
function TP6502.Disassembler(const opCode, par1, par2: byte;
|
function TP6502.DisassemblerAt(addr: word; out nBytesProc: byte;
|
||||||
out nBytesProc: byte;
|
useVarName: boolean): string;
|
||||||
useVarName: boolean = false): string;
|
{Disassembler the instruction located at "addr". If the instruction is multibyte
|
||||||
{Disassemble the instruction indicated in "Opcode". If the instruction is multibyte
|
the intruction length, will be returned in "nBytesProc".
|
||||||
it will be used "par1" and "par2" according to the intruction length, which is returned
|
|
||||||
in "nBytesProc".
|
|
||||||
Global variables used: "idIns", "modIns".
|
Global variables used: "idIns", "modIns".
|
||||||
"useVarName" -> Flag to use the name of the variable instead of only the address.
|
"useVarName" -> Flag to use the name of the variable instead of only the address.
|
||||||
Valid only when a variAble name exists in his address.
|
Valid only when a variAble name exists in his address.
|
||||||
}
|
}
|
||||||
var
|
var
|
||||||
nemo: String;
|
nemo: String;
|
||||||
f: word;
|
opCode, par1, par2: Byte;
|
||||||
begin
|
begin
|
||||||
|
if addr>CPUMAXRAM-1 then exit('');
|
||||||
|
opCode := ram[addr].value;
|
||||||
|
//"par1" and "par2" will be used according to the instruction length.
|
||||||
|
if addr+1>CPUMAXRAM-1 then exit('');
|
||||||
|
par1 := ram[addr+1].value;
|
||||||
Decode(opCode); //Decode instruction. Update: "idIns", "modIns".
|
Decode(opCode); //Decode instruction. Update: "idIns", "modIns".
|
||||||
nemo := trim(PIC16InstName[idIns].name) + ' ';
|
nemo := trim(PIC16InstName[idIns].name) + ' ';
|
||||||
case modIns of
|
case modIns of
|
||||||
aImplicit: begin
|
aImplicit: begin
|
||||||
nBytesProc := 1; //No parameters needed
|
nBytesProc := 1; //No parameters needed
|
||||||
|
Result := nemo;
|
||||||
end;
|
end;
|
||||||
aAcumulat: begin
|
aAcumulat: begin
|
||||||
nBytesProc := 1; //No parameters needed
|
nBytesProc := 1; //No parameters needed
|
||||||
|
Result := nemo;
|
||||||
end;
|
end;
|
||||||
aImmediat: begin
|
aImmediat: begin
|
||||||
Result := nemo + '#$'+IntToHex(par1,2);
|
Result := nemo + '#$'+IntToHex(par1,2);
|
||||||
nBytesProc := 2;
|
nBytesProc := 2;
|
||||||
end;
|
end;
|
||||||
aAbsolute: begin
|
aAbsolute: begin
|
||||||
Result := nemo + '$'+IntToHex(par1 + par2*256, 4);
|
|
||||||
nBytesProc := 3;
|
nBytesProc := 3;
|
||||||
|
if addr+2>CPUMAXRAM-1 then exit('');
|
||||||
|
par2 := ram[addr+2].value;
|
||||||
|
Result := nemo + '$'+IntToHex(par1 + par2*256, 4);
|
||||||
end;
|
end;
|
||||||
aZeroPage: begin
|
aZeroPage: begin
|
||||||
Result := nemo + '$'+IntToHex(par1, 2);
|
Result := nemo + '$'+IntToHex(par1, 2);
|
||||||
nBytesProc := 2;
|
nBytesProc := 2;
|
||||||
end;
|
end;
|
||||||
aRelative: begin
|
aRelative: begin
|
||||||
Result := nemo + '$'+IntToHex(par1, 2);
|
|
||||||
nBytesProc := 2;
|
nBytesProc := 2;
|
||||||
|
if par1<128 then begin //Positive
|
||||||
|
Result := nemo + '$'+IntToHex((addr + par1+2) and $FFFF, 4);
|
||||||
|
end else begin
|
||||||
|
Result := nemo + '$'+IntToHex((addr + par1-254) and $FFFF, 4);
|
||||||
|
end;
|
||||||
|
//Result := nemo + '$'+IntToHex(par1, 2);
|
||||||
end;
|
end;
|
||||||
aIndirect: begin
|
aIndirect: begin
|
||||||
Result := nemo + '$('+IntToHex(par1 + par2*256, 4)+')';
|
|
||||||
nBytesProc := 3;
|
nBytesProc := 3;
|
||||||
|
if addr+2>CPUMAXRAM-1 then exit('');
|
||||||
|
par2 := ram[addr+2].value;
|
||||||
|
Result := nemo + '$('+IntToHex(par1 + par2*256, 4)+')';
|
||||||
end;
|
end;
|
||||||
aAbsolutX: begin
|
aAbsolutX: begin
|
||||||
Result := nemo + '$'+IntToHex(par1 + par2*256, 4)+',X';
|
|
||||||
nBytesProc := 3;
|
nBytesProc := 3;
|
||||||
|
if addr+2>CPUMAXRAM-1 then exit('');
|
||||||
|
par2 := ram[addr+2].value;
|
||||||
|
Result := nemo + '$'+IntToHex(par1 + par2*256, 4)+',X';
|
||||||
end;
|
end;
|
||||||
aAbsolutY: begin
|
aAbsolutY: begin
|
||||||
Result := nemo + '$'+IntToHex(par1 + par2*256, 4)+',Y';
|
|
||||||
nBytesProc := 3;
|
nBytesProc := 3;
|
||||||
|
if addr+2>CPUMAXRAM-1 then exit('');
|
||||||
|
par2 := ram[addr+2].value;
|
||||||
|
Result := nemo + '$'+IntToHex(par1 + par2*256, 4)+',Y';
|
||||||
end;
|
end;
|
||||||
aZeroPagX: begin
|
aZeroPagX: begin
|
||||||
|
nBytesProc := 2;
|
||||||
Result := nemo + '$'+IntToHex(par1, 2)+',X';
|
Result := nemo + '$'+IntToHex(par1, 2)+',X';
|
||||||
nBytesProc := 3;
|
|
||||||
end;
|
end;
|
||||||
aZeroPagY: begin
|
aZeroPagY: begin
|
||||||
|
nBytesProc := 2;
|
||||||
Result := nemo + '$'+IntToHex(par1, 2)+',Y';
|
Result := nemo + '$'+IntToHex(par1, 2)+',Y';
|
||||||
nBytesProc := 3;
|
|
||||||
end;
|
end;
|
||||||
aIdxIndir: begin
|
aIdxIndir: begin
|
||||||
Result := nemo + '$('+IntToHex(par1, 2)+',X)';
|
|
||||||
nBytesProc := 2;
|
nBytesProc := 2;
|
||||||
|
Result := nemo + '$('+IntToHex(par1, 2)+',X)';
|
||||||
end;
|
end;
|
||||||
aIndirIdx: begin
|
aIndirIdx: begin
|
||||||
|
nBytesProc := 2;
|
||||||
Result := nemo + '$('+IntToHex(par1, 2)+'),Y';
|
Result := nemo + '$('+IntToHex(par1, 2)+'),Y';
|
||||||
nBytesProc := 3;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
function TP6502.DisassemblerAt(addr: word; out nBytesProc: byte;
|
|
||||||
useVarName: boolean): string;
|
|
||||||
{Disassembler the instruction located at "addr"}
|
|
||||||
var
|
|
||||||
valOp: Word;
|
|
||||||
begin
|
|
||||||
Result := Disassembler(ram[addr].value,
|
|
||||||
ram[addr+1].value,
|
|
||||||
ram[addr+2].value, nBytesProc, useVarName);
|
|
||||||
end;
|
|
||||||
function TP6502.CurInstruction: TP6502Inst;
|
function TP6502.CurInstruction: TP6502Inst;
|
||||||
{Resturn the instruction pointed by PC, in this moment.}
|
{Return the instruction pointed by PC, in this moment.}
|
||||||
begin
|
begin
|
||||||
Decode(ram[PC.W].value); //decode instruction
|
Decode(ram[PC.W].value); //decode instruction
|
||||||
Result := idIns;
|
Result := idIns;
|
||||||
|
@ -597,11 +605,11 @@ 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;
|
||||||
msk, resNib: byte;
|
|
||||||
nCycles, nBytes: byte;
|
nCycles, nBytes: byte;
|
||||||
resInt : integer;
|
target : word;
|
||||||
begin
|
begin
|
||||||
//Decodifica instrucción
|
//Decodifica instrucción
|
||||||
|
aPC := PC.W;
|
||||||
opc := ram[aPC].value;
|
opc := ram[aPC].value;
|
||||||
Decode(opc); //Decode instruction
|
Decode(opc); //Decode instruction
|
||||||
nCycles := PIC16InstName[idIns].instrInform[modIns].Cycles;
|
nCycles := PIC16InstName[idIns].instrInform[modIns].Cycles;
|
||||||
|
@ -635,24 +643,67 @@ begin
|
||||||
i_INC:; //increment
|
i_INC:; //increment
|
||||||
i_INX:; //increment X
|
i_INX:; //increment X
|
||||||
i_INY:; //increment Y
|
i_INY:; //increment Y
|
||||||
i_JMP:; //jump
|
i_JMP: begin //jump
|
||||||
i_JSR:; //jump subroutine
|
case modIns of
|
||||||
|
aAbsolute : begin
|
||||||
|
PC.L := ram[aPC+1].value;
|
||||||
|
PC.H := ram[aPC+2].value;
|
||||||
|
end;
|
||||||
|
aIndirect: begin
|
||||||
|
target := ram[aPC+1].value + 256* ram[aPC+2].value;
|
||||||
|
PC.L := ram[target+1].value;
|
||||||
|
PC.H := ram[target+2].value;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
//Inc(PC.W, nBytes); //No apply
|
||||||
|
Inc(nClck, nCycles);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
i_JSR: begin
|
||||||
|
inc(PC.W, 3); //Next psoition
|
||||||
|
//Save return
|
||||||
|
ram[$100 + SP].value := PC.H;
|
||||||
|
if SP = $00 then SP := $FF else dec(SP);
|
||||||
|
ram[$100 + SP].value := PC.L;
|
||||||
|
if SP = $00 then SP := $FF else dec(SP);
|
||||||
|
PC.L := ram[aPC+1].value;
|
||||||
|
PC.H := ram[aPC+2].value;
|
||||||
|
//Inc(PC.W, nBytes); //No apply
|
||||||
|
Inc(nClck, nCycles);
|
||||||
|
exit;
|
||||||
|
end; //jump subroutine
|
||||||
i_LDA:; //load accumulator
|
i_LDA:; //load accumulator
|
||||||
i_LDX:; //load X
|
i_LDX:; //load X
|
||||||
i_LDY:; //load Y
|
i_LDY:; //load Y
|
||||||
i_LSR:; //logical shift right
|
i_LSR:; //logical shift right
|
||||||
i_NOP:; //no operation
|
i_NOP:; //no operation
|
||||||
i_ORA:; //or with accumulator
|
i_ORA:; //or with accumulator
|
||||||
i_PHA:; //push accumulator
|
i_PHA: begin //push accumulator
|
||||||
|
ram[$100 + SP].value := W;
|
||||||
|
if SP = $00 then SP := $FF else dec(SP);
|
||||||
|
end;
|
||||||
i_PHP:; //push processor status (SR)
|
i_PHP:; //push processor status (SR)
|
||||||
i_PLA:; //pull accumulator
|
i_PLA: begin //pull accumulator
|
||||||
|
if SP = $FF then SP := $00 else inc(SP);
|
||||||
|
W := ram[$100 + SP].value;
|
||||||
|
end;
|
||||||
i_PLP:; //pull processor status (SR)
|
i_PLP:; //pull processor status (SR)
|
||||||
i_ROL:; //rotate left
|
i_ROL:; //rotate left
|
||||||
i_ROR:; //rotate right
|
i_ROR:; //rotate right
|
||||||
i_RTI:; //return from interrupt
|
i_RTI:; //return from interrupt
|
||||||
i_RTS:; //return from subroutine
|
i_RTS: begin //return from subroutine
|
||||||
|
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_SBC:; //subtract with carry
|
i_SBC:; //subtract with carry
|
||||||
i_SEC:; //set carry
|
i_SEC: begin //set carry
|
||||||
|
STATUS_C := true;
|
||||||
|
end;
|
||||||
i_SED:; //set decimal
|
i_SED:; //set decimal
|
||||||
i_SEI:; //set interrupt disable
|
i_SEI:; //set interrupt disable
|
||||||
i_STA:; //store accumulator
|
i_STA:; //store accumulator
|
||||||
|
@ -889,13 +940,13 @@ begin
|
||||||
end;
|
end;
|
||||||
i_CALL: begin
|
i_CALL: begin
|
||||||
//Guarda dirección en Pila
|
//Guarda dirección en Pila
|
||||||
STACK[STKPTR] := PC.W;
|
STACK[SP] := PC.W;
|
||||||
if STKPTR = 7 then begin
|
if SP = 7 then begin
|
||||||
//Desborde de pila
|
//Desborde de pila
|
||||||
STKPTR := 0;
|
SP := 0;
|
||||||
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on CALL OpCode at $' + IntToHex(aPC,4));
|
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on CALL OpCode at $' + IntToHex(aPC,4));
|
||||||
end else begin
|
end else begin
|
||||||
STKPTR := STKPTR +1;
|
SP := SP +1;
|
||||||
end;
|
end;
|
||||||
PC.W := k_; //Takes the 11 bits from k
|
PC.W := k_; //Takes the 11 bits from k
|
||||||
PC.H := PC.H or (PCLATH and %00011000); //And complete with bits 3 and 4 of PCLATH
|
PC.H := PC.H or (PCLATH and %00011000); //And complete with bits 3 and 4 of PCLATH
|
||||||
|
@ -920,42 +971,42 @@ begin
|
||||||
end;
|
end;
|
||||||
i_RETFIE: begin
|
i_RETFIE: begin
|
||||||
//Saca dirección en Pila
|
//Saca dirección en Pila
|
||||||
if STKPTR = 0 then begin
|
if SP = 0 then begin
|
||||||
//Desborde de pila
|
//Desborde de pila
|
||||||
STKPTR := 7;
|
SP := 7;
|
||||||
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on RETFIE OpCode at $' + IntToHex(aPC,4));
|
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on RETFIE OpCode at $' + IntToHex(aPC,4));
|
||||||
end else begin
|
end else begin
|
||||||
STKPTR := STKPTR - 1;
|
SP := SP - 1;
|
||||||
end;
|
end;
|
||||||
PC.W := STACK[STKPTR]; //Should be 13 bits
|
PC.W := STACK[SP]; //Should be 13 bits
|
||||||
Inc(nClck); //Esta instrucción toma un ciclo más
|
Inc(nClck); //Esta instrucción toma un ciclo más
|
||||||
//Activa GIE
|
//Activa GIE
|
||||||
INTCON_GIE := true;
|
INTCON_GIE := true;
|
||||||
end;
|
end;
|
||||||
i_RETLW: begin
|
i_RETLW: begin
|
||||||
//Saca dirección en Pila
|
//Saca dirección en Pila
|
||||||
if STKPTR = 0 then begin
|
if SP = 0 then begin
|
||||||
//Desborde de pila
|
//Desborde de pila
|
||||||
STKPTR := 7;
|
SP := 7;
|
||||||
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on RETLW OpCode at $' + IntToHex(aPC,4));
|
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on RETLW OpCode at $' + IntToHex(aPC,4));
|
||||||
end else begin
|
end else begin
|
||||||
STKPTR := STKPTR - 1;
|
SP := SP - 1;
|
||||||
end;
|
end;
|
||||||
PC.W := STACK[STKPTR]; //Should be 13 bits
|
PC.W := STACK[SP]; //Should be 13 bits
|
||||||
Inc(nClck); //Esta instrucción toma un ciclo más
|
Inc(nClck); //Esta instrucción toma un ciclo más
|
||||||
//Fija valor en W
|
//Fija valor en W
|
||||||
W := k_;
|
W := k_;
|
||||||
end;
|
end;
|
||||||
i_RETURN: begin
|
i_RETURN: begin
|
||||||
//Saca dirección en Pila
|
//Saca dirección en Pila
|
||||||
if STKPTR = 0 then begin
|
if SP = 0 then begin
|
||||||
//Desborde de pila
|
//Desborde de pila
|
||||||
STKPTR := 7;
|
SP := 7;
|
||||||
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on RETURN OpCode at $' + IntToHex(aPC,4));
|
if OnExecutionMsg<>nil then OnExecutionMsg('Stack Overflow on RETURN OpCode at $' + IntToHex(aPC,4));
|
||||||
end else begin
|
end else begin
|
||||||
STKPTR := STKPTR - 1;
|
SP := SP - 1;
|
||||||
end;
|
end;
|
||||||
PC.W := STACK[STKPTR]; //Should be 13 bits
|
PC.W := STACK[SP]; //Should be 13 bits
|
||||||
Inc(nClck); //Esta instrucción toma un ciclo más
|
Inc(nClck); //Esta instrucción toma un ciclo más
|
||||||
end;
|
end;
|
||||||
i_SLEEP: begin
|
i_SLEEP: begin
|
||||||
|
@ -1053,7 +1104,7 @@ begin
|
||||||
end;
|
end;
|
||||||
stopped := false;
|
stopped := false;
|
||||||
end;
|
end;
|
||||||
procedure TP6502.Reset;
|
procedure TP6502.Reset(hard: boolean);
|
||||||
//Reinicia el dipsoitivo
|
//Reinicia el dipsoitivo
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
@ -1061,12 +1112,14 @@ begin
|
||||||
PC.W := 0;
|
PC.W := 0;
|
||||||
PCLATH := 0;
|
PCLATH := 0;
|
||||||
W := 0;
|
W := 0;
|
||||||
STKPTR := 0; //Posición inicial del puntero de pila
|
SP := $FF; //Posición inicial del puntero de pila
|
||||||
nClck := 0; //Inicia contador de ciclos
|
nClck := 0; //Inicia contador de ciclos
|
||||||
CommStop := false; //Limpia bandera
|
CommStop := false; //Limpia bandera
|
||||||
//Limpia solamente el valor inicial, no toca los otros campos
|
if hard then begin
|
||||||
for i:=0 to high(ram) do begin
|
//Limpia solamente el valor inicial, no toca los otros campos
|
||||||
ram[i].dvalue := $00;
|
for i:=0 to high(ram) do begin
|
||||||
|
ram[i].dvalue := $00;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
ram[_STATUS].dvalue := %00011000; //STATUS
|
ram[_STATUS].dvalue := %00011000; //STATUS
|
||||||
end;
|
end;
|
||||||
|
@ -1080,18 +1133,18 @@ begin
|
||||||
end;
|
end;
|
||||||
//Funciones para la memoria RAM
|
//Funciones para la memoria RAM
|
||||||
function TP6502.GetFreeByte(out addr: word; shared: boolean): boolean;
|
function TP6502.GetFreeByte(out addr: word; shared: boolean): boolean;
|
||||||
{Devuelve una dirección libre de la memoria RAM.
|
{Devuelve una dirección libre de la memoria RAM, a partir de la dirección iRam.
|
||||||
"Shared" indica que se marcará el bit como de tipo "Compartido", y se usa para el
|
"Shared" indica que se marcará el bit como de tipo "Compartido", y se usa para el
|
||||||
caso en que se quiera comaprtir la misma posición para diversos variables.
|
caso en que se quiera comaprtir la misma posición para diversos variables.
|
||||||
Si encuentra espacio, devuelve TRUE.}
|
Si encuentra espacio, devuelve TRUE.}
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
maxRam: word;
|
maxRam: dword;
|
||||||
begin
|
begin
|
||||||
Result := false; //valor inicial
|
Result := false; //valor inicial
|
||||||
maxRam := CPUMAXRAM; //posición máxima
|
maxRam := CPUMAXRAM; //posición máxima
|
||||||
//Realmente debería explorar solo hasta la dirección implementada, por eficiencia
|
//Realmente debería explorar solo hasta la dirección implementada, por eficiencia
|
||||||
for i:=0 to maxRam-1 do begin
|
for i:=iRam to maxRam-1 do begin
|
||||||
if (ram[i].state = cs_impleGPR) and (not ram[i].used) then begin
|
if (ram[i].state = cs_impleGPR) and (not ram[i].used) then begin
|
||||||
//Esta dirección está libre
|
//Esta dirección está libre
|
||||||
ram[i].used := true; //marca como usado
|
ram[i].used := true; //marca como usado
|
||||||
|
@ -1126,14 +1179,14 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
function TP6502.TotalMemRAM: word;
|
function TP6502.TotalMemRAM: integer;
|
||||||
{Devuelve el total de memoria RAM disponible}
|
{Devuelve el total de memoria RAM disponible}
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
for i := 0 to CPUMAXRAM - 1 do begin
|
for i := 0 to CPUMAXRAM - 1 do begin
|
||||||
if ram[i].AvailGPR then begin
|
if ram[i].Avail then begin
|
||||||
Result := Result + 1;
|
Result := Result + 1;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -1145,7 +1198,7 @@ var
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
for i := 0 to CPUMAXRAM - 1 do begin
|
for i := 0 to CPUMAXRAM - 1 do begin
|
||||||
if ram[i].AvailGPR and (ram[i].used) then begin
|
if ram[i].Avail and (ram[i].used) then begin
|
||||||
//Notar que "AvailGPR" asegura que no se consideran registros maepados
|
//Notar que "AvailGPR" asegura que no se consideran registros maepados
|
||||||
Result := Result + 1;
|
Result := Result + 1;
|
||||||
end;
|
end;
|
||||||
|
@ -1157,7 +1210,7 @@ var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
for i := 0 to CPUMAXRAM - 1 do begin
|
for i := 0 to CPUMAXRAM - 1 do begin
|
||||||
if ram[i].AvailGPR and (ram[i].used) then begin
|
if ram[i].Avail and (ram[i].used) then begin
|
||||||
rutExplorRAM(i, @ram[i]);
|
rutExplorRAM(i, @ram[i]);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -1168,37 +1221,13 @@ 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;
|
||||||
procedure TP6502.GenHex(hexFile: string; ConfigWord: integer = -1);
|
procedure TP6502.DumpCodeAsm(lOut: TStrings;
|
||||||
{Genera el archivo *.hex, a partir de los datos almacenados en la memoria RAM.
|
incAdrr, incValues, incCom, incVarNam: boolean);
|
||||||
Actualiza los campos, minUsed y maxUsed.}
|
|
||||||
var
|
|
||||||
iHex: word; //Índice para explorar
|
|
||||||
addr: word; //Dirección de inicio
|
|
||||||
i: Integer;
|
|
||||||
|
|
||||||
begin
|
|
||||||
hexLines.Clear; //Se usará la lista hexLines
|
|
||||||
//Prepara extracción de datos
|
|
||||||
minUsed := CPUMAXRAM;
|
|
||||||
maxUsed := 0;
|
|
||||||
iHex := 0;
|
|
||||||
//Busca dirección de inicio usada
|
|
||||||
for i := 0 to CPUMAXRAM-1 do begin
|
|
||||||
if ram[i].used then begin
|
|
||||||
if i<minUsed then minUsed := i;
|
|
||||||
if i>maxUsed then maxUsed := i;
|
|
||||||
hexLines.Add('poke ' + IntToStr(i) + ',' + IntToStr(ram[i].value));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
//hexLines.Add('Comentario');
|
|
||||||
hexLines.SaveToFile(hexFile); //Genera archivo
|
|
||||||
end;
|
|
||||||
procedure TP6502.DumpCode(lOut: TStrings; incAdrr, 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}
|
||||||
var
|
var
|
||||||
i: Word;
|
i: Word;
|
||||||
lblLin, comLat, comLin, lin: String;
|
lblLin, comLat, comLin, lin, opCode: String;
|
||||||
nBytes: byte;
|
nBytes: byte;
|
||||||
const
|
const
|
||||||
SPACEPAD = ' ';
|
SPACEPAD = ' ';
|
||||||
|
@ -1233,11 +1262,27 @@ begin
|
||||||
lOut.Add(comLin);
|
lOut.Add(comLin);
|
||||||
end;
|
end;
|
||||||
//Decodifica instrucción
|
//Decodifica instrucción
|
||||||
lin := DisassemblerAt(i, nBytes, incVarNam); //Instrucción
|
opCode := DisassemblerAt(i, nBytes, incVarNam); //Instrucción
|
||||||
//Verificas si incluye dirección física
|
//Verificas si incluye dirección física
|
||||||
|
lin := '';
|
||||||
if incAdrr then begin
|
if incAdrr then begin
|
||||||
lin := '$'+IntToHex(i,4) + ' ' + lin;
|
//Agrega dirección al inicio
|
||||||
|
lin := '$'+IntToHex(i,4) + ' ';
|
||||||
end;
|
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 := lin + opCode;
|
||||||
//Verifica si incluye comentario lateral
|
//Verifica si incluye comentario lateral
|
||||||
if incCom then begin
|
if incCom then begin
|
||||||
lin := lin + ' ' + comLat;
|
lin := lin + ' ' + comLat;
|
||||||
|
@ -1246,12 +1291,32 @@ begin
|
||||||
i := i + nBytes; //Incrementa a siguiente instrucción
|
i := i + nBytes; //Incrementa a siguiente instrucción
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
procedure TP6502.GenHex(hexFile: string);
|
||||||
|
{Genera el archivo *.hex, a partir de los datos almacenados en la memoria RAM.
|
||||||
|
Actualiza los campos, minUsed y maxUsed.}
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
hexLines.Clear; //Se usará la lista hexLines
|
||||||
|
//Prepara extracción de datos
|
||||||
|
minUsed := CPUMAXRAM;
|
||||||
|
maxUsed := 0;
|
||||||
|
//Busca dirección de inicio usada
|
||||||
|
for i := 0 to CPUMAXRAM-1 do begin
|
||||||
|
if ram[i].used then begin
|
||||||
|
if i<minUsed then minUsed := i;
|
||||||
|
if i>maxUsed then maxUsed := i;
|
||||||
|
hexLines.Add('poke ' + IntToStr(i) + ',' + IntToStr(ram[i].value));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
hexLines.SaveToFile(hexFile); //Genera archivo
|
||||||
|
end;
|
||||||
constructor TP6502.Create;
|
constructor TP6502.Create;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
//Default hardware settings
|
//Default hardware settings
|
||||||
Model := '6502';
|
Model := '6502';
|
||||||
CPUMAXRAM := 4096; //Máx RAM memory
|
CPUMAXRAM := $10000; //Máx RAM memory
|
||||||
SetLength(ram, CPUMAXRAM);
|
SetLength(ram, CPUMAXRAM);
|
||||||
//inicia una configuración común
|
//inicia una configuración común
|
||||||
ClearMemRAM;
|
ClearMemRAM;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user