I rarely have to return several values as a function result -
out variables are also an option, or passing the record as a
var parameter by the caller and to be filled out by the subroutine. But, if I were to use this tuple feature I'd probably refer to the fields via names.
5. Pascal is 1-based
Strings, default arrays - Pascal starts from 1. _1 is natural.
Well, dynamic arrays also start at zero.
- - -
This has nothing to do with any existing feature of FPCU, but:
While I'm coding a state machine, I also define a macro with the current index. I can then use this macro as a constant value in conditional compiling:
const
SingleByteOpcodes =
[ $08, $0A, $0B
, $18, $1A, $1B
, $28, $2A, $2B
, $38, $3A, $3B
, $40, $48, $4A, $4B
, $58, $5A, $5B
, $68, $6A, $6B
, $78, $7A, $7B
, $80, $88, $8A, $8B
, $98, $9A, $9B
, $A8, $AA, $AB
, $B8, $BA, $BB
, $C8, $CA, $CB
, $D8, $DA, $DB
, $E8, $EA, $EB
, $F8, $FA, $FB];
//...
// unconditional fetch
{$define Fetch_FirstParam := begin
MDR := Fetch(PC, MDR);
{$if not (Op in SingleByteOpcodes)} PC := u16(PC + 1); {$endif}
end}
// ...
{$define Op := $00} Opcode[Op]: // BRK (software interrupt) or IRQ/NMI/RESET (hardware interrupt)
if stop then goto Unload; // loop exit
Resume: // loop entry
{1} Fetch_FirstParam;
{2} MDR := PCH; if is_RESET then MDR := Pull (S, MDR) else Push(S, MDR); Dec_S; // push PC
{3} MDR := PCL; if is_RESET then MDR := Pull (S, MDR) else Push(S, MDR); Dec_S; // push PC
{4} MDR := P; Get_Vector; Push (S, MDR); Dec_S; // store vector in PC, push P
{5} i := 1; MDR := Fetch(PC, MDR); Data := MDR; Inc_PC; // disable IRQs, fetch pointer
{6} MDR := Fetch(PC, MDR); DataH := MDR; Inc_PC; // fetch pointer
{7} NMI := high(NMI); MDR := Fetch(PC, MDR); IR := MDR; Inc_PC; Dispatch; // clear NMI, fetch opcode (no interrupt check)
// ...
The
{$if} compiler directive is very basic. It doesn't seem to understand arrays, so I have to define
SingleByteOpcodes as a set. Maybe this could be expanded to any constant value... just an idea.