////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
// LIGHT8080 CORE MICROCODE (V.1 November 1st 2007)
|
// LIGHT8080 CORE MICROCODE (V.2 February 12th 2012)
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
// NOTE: Except for bug fixing, there's no need to tinker with the microcode.
|
// NOTE: Except for bug fixing, there's no need to tinker with the microcode.
|
// Once the microcode table has been generated, this file is is not needed to
|
// Once the microcode table has been generated, this file is is not needed to
|
// synthesize or use the core.
|
// synthesize or use the core.
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// ***** FORMAT AND OPERATION:
|
// ***** FORMAT AND OPERATION:
|
//
|
//
|
// operation 1 ; operation 2 ; flags
|
// operation 1 ; operation 2 ; flags
|
//
|
//
|
// Operation 1 sets up the ALU input registers; operation 2 takes the ALU result
|
// Operation 1 sets up the ALU input registers; operation 2 takes the ALU result
|
// and writes it back somewhere; and the flags group all other microinstruction
|
// and writes it back somewhere; and the flags group all other microinstruction
|
// control signals.
|
// control signals.
|
//
|
//
|
// For any given microinstruction, operation 2 takes place in the cycle after
|
// For any given microinstruction, operation 2 takes place in the cycle after
|
// operation 1. It happens concurrently with the next microinstruction's
|
// operation 1. It happens concurrently with the next microinstruction's
|
// operation 1, so whenever a register is written to in an operation 2 it will
|
// operation 1, so whenever a register is written to in an operation 2 it will
|
// NOT be available for the next microinstruction.
|
// NOT be available for the next microinstruction.
|
//
|
//
|
// In operation 1, you may load any one of T1 or T2 from the register bank or
|
// In operation 1, you may load any one of T1 or T2 from the register bank or
|
// from DI which is simply the unregistered signal data_in.
|
// from DI which is simply the unregistered signal data_in.
|
//
|
//
|
// In operation 2, you specify the ALU operation and assign the ALU result to
|
// In operation 2, you specify the ALU operation and assign the ALU result to
|
// the register bank or the register DO, which feeds the signal data_out.
|
// the register bank or the register DO, which feeds the signal data_out.
|
//
|
//
|
// You cannot address two different registers from the register bank in
|
// You cannot address two different registers from the register bank in
|
// operations 1 and 2 (see the design notes on this).
|
// operations 1 and 2 (see the design notes on this).
|
//
|
//
|
// *** Some other elements found in the microcode source:
|
// *** Some other elements found in the microcode source:
|
//
|
//
|
// labels: must be in a line by themselves, otherwise work like any assembler.
|
// labels: must be in a line by themselves, otherwise work like any assembler.
|
// __code pragmas: used by assembler to automatically generate the decode table.
|
// __code pragmas: used by assembler to automatically generate the decode table.
|
// __asm pragmas: not used, but can be handy as a reference.
|
// __asm pragmas: not used, but can be handy as a reference.
|
//
|
//
|
//
|
//
|
// ***** FLAGS:
|
// ***** FLAGS:
|
//
|
//
|
// Note: '1st cycle' and '2nd cycle' denote both cycles of the present
|
// Note: '1st cycle' and '2nd cycle' denote both cycles of the present
|
// microinstruction (m.i.); cycle 2 of m.i. N overlaps cycle 1 of m.i. N+1.
|
// microinstruction (m.i.); cycle 2 of m.i. N overlaps cycle 1 of m.i. N+1.
|
//
|
//
|
// #ld_al : Load AL register with register bank output as read by operation 1.
|
// #ld_al : Load AL register with register bank output as read by operation 1.
|
// (used in memory and io access).
|
// (used in memory and io access).
|
// #ld_addr : Load address register (H byte = register bank output as read by
|
// #ld_addr : Load address register (H byte = register bank output as read by
|
// operation 1, L byte = AL).
|
// operation 1, L byte = AL).
|
// Activate vma signal for 1st cycle.
|
// Activate vma signal for 1st cycle.
|
// #auxcy : Use aux carry instead of regular carry for this operation.
|
// #auxcy : Use aux carry instead of regular carry for this operation.
|
// #setacy : Set aux carry at the start of 1st cycle (used for ++).
|
// #setacy : Set aux carry at the start of 1st cycle (used for ++).
|
// #end : Jump to microinstruction address 3 after the present m.i.
|
// #end : Jump to microinstruction address 3 after the present m.i.
|
// #ret : Jump to address saved by the last JST or TJSR m.i.
|
// #ret : Jump to address saved by the last JST or TJSR m.i.
|
// #rd : Activate rd signal for the 2nd cycle.
|
// #rd : Activate rd signal for the 2nd cycle.
|
// #wr : Activate wr signal for the 2nd cycle.
|
// #wr : Activate wr signal for the 2nd cycle.
|
// #fp_r : This microinstruction updates all PSW flags except for C.
|
// #fp_r : This microinstruction updates all PSW flags except for C.
|
// #fp_c : This microinstruction updates only the C flag in the PSW.
|
// #fp_c : This microinstruction updates only the C flag in the PSW.
|
// #fp_rc : This microinstruction updates all the flags in the PSW.
|
// #fp_rc : This microinstruction updates all the flags in the PSW.
|
// #clrt1 : Clear T1 at the end of 1st cycle.
|
// #clrt1 : Clear T1 at the end of 1st cycle.
|
// #io : Activate io signal for 1st cycle.
|
// #io : Activate io signal for 1st cycle.
|
// #ei : Set interrupt enable register.
|
// #ei : Set interrupt enable register.
|
// #di : Reset interrupt enable register.
|
// #di : Reset interrupt enable register.
|
// #halt : Jump to microcode address 0x07 without saving return value.
|
// #halt : Jump to microcode address 0x07 without saving return value.
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
|
// V.1 November 1st 2007 -- Original version
|
|
// V.2 February 12th 2012 -- Fixed CY/AC clear bug with clr_acy flag
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// RESET ucode: from 0 to 2, but uinst at address 0 is never executed
|
// RESET ucode: from 0 to 2, but uinst at address 0 is never executed
|
__reset
|
__reset
|
|
|
NOP ; NOP
|
NOP ; NOP
|
NOP ; _pl = AND ; // T1 & T2 = 0x00
|
NOP ; _pl = AND ; // T1 & T2 = 0x00
|
NOP ; _ph = AND ; // T1 & T2 = 0x00
|
NOP ; _ph = AND ; // T1 & T2 = 0x00
|
|
|
// FETCH ucode: from 3 to 6
|
// FETCH ucode: from 3 to 6
|
// (executed in INTA cycles too, with pc increment inhibited to preserve PC)
|
// (executed in INTA cycles too, with pc increment inhibited to preserve PC)
|
__fetch
|
__fetch
|
|
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
NOP ; NOP ; #decode
|
NOP ; NOP ; #decode
|
|
|
// free uinst slot
|
// free uinst slot
|
NOP ; NOP ;
|
NOP ; NOP ;
|
|
|
// HALT ucode: address 7
|
// HALT ucode: address 7
|
__halt
|
__halt
|
NOP ; NOP ; #halt, #end
|
NOP ; NOP ; #halt, #end
|
|
|
|
|
// NOTE: ALU single_operand ops work on T1
|
// NOTE: ALU single_operand ops work on T1
|
// ALU 2-operands work with 'A' on T2 (e.g. SUB == T2 - T1)
|
// ALU 2-operands work with 'A' on T2 (e.g. SUB == T2 - T1)
|
|
|
|
|
__code "01dddsss"
|
__code "01dddsss"
|
__asm MOV {d},{s}
|
__asm MOV {d},{s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
NOP ; {d} = T1 ; #end
|
NOP ; {d} = T1 ; #end
|
|
|
|
|
__code "01ddd110"
|
__code "01ddd110"
|
__asm MOV {d},M
|
__asm MOV {d},M
|
|
|
JSR read_m ;
|
JSR read_m ;
|
NOP ; {d} = T1 ; #end
|
NOP ; {d} = T1 ; #end
|
|
|
|
|
__code "01110sss"
|
__code "01110sss"
|
__asm MOV M,{s}
|
__asm MOV M,{s}
|
|
|
T1 = {s} ; DO = T1
|
T1 = {s} ; DO = T1
|
JSR write_m // does not return
|
JSR write_m // does not return
|
|
|
|
|
__code "00ddd110"
|
__code "00ddd110"
|
__asm MVI {d},#imm
|
__asm MVI {d},#imm
|
|
|
JSR read_imm
|
JSR read_imm
|
NOP ; {d} = T1 ; #end
|
NOP ; {d} = T1 ; #end
|
|
|
|
|
__code "00110110"
|
__code "00110110"
|
__asm MVI M,#imm
|
__asm MVI M,#imm
|
|
|
JSR read_imm
|
JSR read_imm
|
JSR write_m
|
JSR write_m
|
|
|
|
|
__code "00pp0001"
|
__code "00pp0001"
|
__asm LXI [p]
|
__asm LXI [p]
|
|
|
JSR read_imm
|
JSR read_imm
|
NOP ; {p}1 = T1
|
NOP ; {p}1 = T1
|
JSR read_imm
|
JSR read_imm
|
NOP ; {p}0 = T1 ; #end
|
NOP ; {p}0 = T1 ; #end
|
|
|
|
|
__code "00111010"
|
__code "00111010"
|
__asm LDA addr
|
__asm LDA addr
|
|
|
JSR read_imm_wz
|
JSR read_imm_wz
|
JSR read_wz
|
JSR read_wz
|
NOP ; _a = T1 ; #end
|
NOP ; _a = T1 ; #end
|
|
|
|
|
__code "00110010"
|
__code "00110010"
|
__asm STA addr
|
__asm STA addr
|
|
|
JSR read_imm_wz
|
JSR read_imm_wz
|
T1 = _a ; DO = T1 ;
|
T1 = _a ; DO = T1 ;
|
JSR write_wz //does not return
|
JSR write_wz //does not return
|
|
|
|
|
__code "00101010"
|
__code "00101010"
|
__asm LHLD
|
__asm LHLD
|
|
|
|
|
JSR read_imm_wz
|
JSR read_imm_wz
|
T1 = _z ; _z = ADC ; #ld_al, #auxcy, #setacy // L = (WZ++)
|
T1 = _z ; _z = ADC ; #ld_al, #auxcy, #setacy // L = (WZ++)
|
T1 = _w ; _w = ADC ; #ld_addr, #rd, #auxcy
|
T1 = _w ; _w = ADC ; #ld_addr, #rd, #auxcy
|
T1 = DI ; _l = T1
|
T1 = DI ; _l = T1
|
JSR read_wz // H = (WZ)
|
JSR read_wz // H = (WZ)
|
NOP ; _h = T1 ; #end
|
NOP ; _h = T1 ; #end
|
|
|
|
|
__code "00100010"
|
__code "00100010"
|
__asm SHLD
|
__asm SHLD
|
|
|
JSR read_imm_wz
|
JSR read_imm_wz
|
T1 = _l ; DO = T1
|
T1 = _l ; DO = T1
|
T1 = _z ; _z = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _z ; _z = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _w ; _w = ADC ; #ld_addr, #wr, #auxcy
|
T1 = _w ; _w = ADC ; #ld_addr, #wr, #auxcy
|
T1 = _h ; DO = T1
|
T1 = _h ; DO = T1
|
JSR write_wz
|
JSR write_wz
|
|
|
|
|
__code "00pp1010"
|
__code "00pp1010"
|
__asm LDAX [p]
|
__asm LDAX [p]
|
|
|
JSR read_p
|
JSR read_p
|
NOP ; _a = T1 ; #end
|
NOP ; _a = T1 ; #end
|
|
|
|
|
__code "00pp0010"
|
__code "00pp0010"
|
__asm STAX [p]
|
__asm STAX [p]
|
|
|
T1 = _a ; DO = T1
|
T1 = _a ; DO = T1
|
JSR write_p
|
JSR write_p
|
|
|
|
|
__code "11101011"
|
__code "11101011"
|
__asm XCHG
|
__asm XCHG
|
|
|
// 16 T cycles vs. 10 for the original 8080...
|
// 16 T cycles vs. 10 for the original 8080...
|
T1 = _d ; NOP
|
T1 = _d ; NOP
|
NOP ; _x = T1
|
NOP ; _x = T1
|
T1 = _e ; NOP
|
T1 = _e ; NOP
|
NOP ; _y = T1
|
NOP ; _y = T1
|
T1 = _h ; NOP
|
T1 = _h ; NOP
|
NOP ; _d = T1
|
NOP ; _d = T1
|
T1 = _l ; NOP
|
T1 = _l ; NOP
|
NOP ; _e = T1
|
NOP ; _e = T1
|
T1 = _x ; NOP
|
T1 = _x ; NOP
|
NOP ; _h = T1
|
NOP ; _h = T1
|
T1 = _y ; NOP
|
T1 = _y ; NOP
|
NOP ; _l = T1 ; #end
|
NOP ; _l = T1 ; #end
|
|
|
|
|
__code "11000110"
|
__code "11000110"
|
__asm ADI #imm
|
__asm ADI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; _a = ADD ; #end, #fp_rc
|
T2 = _a ; _a = ADD ; #end, #fp_rc
|
|
|
__code "11001110"
|
__code "11001110"
|
__asm ACI #imm
|
__asm ACI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; _a = ADC ; #end, #fp_rc
|
T2 = _a ; _a = ADC ; #end, #fp_rc
|
|
|
__code "11010110"
|
__code "11010110"
|
__asm SUI #imm
|
__asm SUI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; _a = SUB ; #end, #fp_rc
|
T2 = _a ; _a = SUB ; #end, #fp_rc
|
|
|
__code "11011110"
|
__code "11011110"
|
__asm SBI #imm
|
__asm SBI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; _a = SBB ; #end, #fp_rc
|
T2 = _a ; _a = SBB ; #end, #fp_rc
|
|
|
|
|
__code "11100110"
|
__code "11100110"
|
__asm ANI #imm
|
__asm ANI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; _a = AND ; #end, #fp_rc
|
T2 = _a ; _a = AND ; #end, #fp_rc, #clr_acy
|
|
|
__code "11101110"
|
__code "11101110"
|
__asm XRI #imm
|
__asm XRI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; _a = XRL ; #end, #fp_rc
|
T2 = _a ; _a = XRL ; #end, #fp_rc, #clr_acy
|
|
|
|
|
__code "11110110"
|
__code "11110110"
|
__asm ORI #imm
|
__asm ORI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; _a = ORL ; #end, #fp_rc
|
T2 = _a ; _a = ORL ; #end, #fp_rc, #clr_acy
|
|
|
|
|
__code "11111110"
|
__code "11111110"
|
__asm CPI #imm
|
__asm CPI #imm
|
|
|
JSR read_imm
|
JSR read_imm
|
T2 = _a ; DO = SUB ; #end, #fp_rc
|
T2 = _a ; DO = SUB ; #end, #fp_rc
|
|
|
|
|
|
|
__code "10000sss"
|
__code "10000sss"
|
__asm ADD {s}
|
__asm ADD {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; _a = ADD ; #end, #fp_rc
|
T2 = _a ; _a = ADD ; #end, #fp_rc
|
|
|
__code "10001sss"
|
__code "10001sss"
|
__asm ADC {s}
|
__asm ADC {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; _a = ADC ; #end, #fp_rc
|
T2 = _a ; _a = ADC ; #end, #fp_rc
|
|
|
__code "10010sss"
|
__code "10010sss"
|
__asm SUB {s}
|
__asm SUB {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; _a = SUB ; #end, #fp_rc
|
T2 = _a ; _a = SUB ; #end, #fp_rc
|
|
|
__code "10011sss"
|
__code "10011sss"
|
__asm SBB {s}
|
__asm SBB {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; _a = SBB ; #end, #fp_rc
|
T2 = _a ; _a = SBB ; #end, #fp_rc
|
|
|
__code "10100sss"
|
__code "10100sss"
|
__asm ANA {s}
|
__asm ANA {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; _a = AND ; #end, #fp_rc
|
T2 = _a ; _a = AND ; #end, #fp_rc, #clr_acy
|
|
|
__code "10101sss"
|
__code "10101sss"
|
__asm XRA {s}
|
__asm XRA {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; _a = XRL ; #end, #fp_rc
|
T2 = _a ; _a = XRL ; #end, #fp_rc, #clr_acy
|
|
|
__code "10110sss"
|
__code "10110sss"
|
__asm ORA {s}
|
__asm ORA {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; _a = ORL ; #end, #fp_rc
|
T2 = _a ; _a = ORL ; #end, #fp_rc, #clr_acy
|
|
|
__code "10111sss"
|
__code "10111sss"
|
__asm CMP {s}
|
__asm CMP {s}
|
|
|
T1 = {s} ; NOP
|
T1 = {s} ; NOP
|
T2 = _a ; DO = SUB ; #end, #fp_rc
|
T2 = _a ; DO = SUB ; #end, #fp_rc
|
|
|
|
|
__code "10000110"
|
__code "10000110"
|
__asm ADD M
|
__asm ADD M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; _a = ADD ; #end, #fp_rc
|
T2 = _a ; _a = ADD ; #end, #fp_rc
|
|
|
__code "10001110"
|
__code "10001110"
|
__asm ADC M
|
__asm ADC M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; _a = ADC ; #end, #fp_rc
|
T2 = _a ; _a = ADC ; #end, #fp_rc
|
|
|
__code "10010110"
|
__code "10010110"
|
__asm SUB M
|
__asm SUB M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; _a = SUB ; #end, #fp_rc
|
T2 = _a ; _a = SUB ; #end, #fp_rc
|
|
|
__code "10011110"
|
__code "10011110"
|
__asm SBB M
|
__asm SBB M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; _a = SBB ; #end, #fp_rc
|
T2 = _a ; _a = SBB ; #end, #fp_rc
|
|
|
__code "10100110"
|
__code "10100110"
|
__asm ANA M
|
__asm ANA M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; _a = AND ; #end, #fp_rc
|
T2 = _a ; _a = AND ; #end, #fp_rc, #clr_acy
|
|
|
__code "10101110"
|
__code "10101110"
|
__asm XRA M
|
__asm XRA M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; _a = XRL ; #end, #fp_rc
|
T2 = _a ; _a = XRL ; #end, #fp_rc, #clr_acy
|
|
|
__code "10110110"
|
__code "10110110"
|
__asm ORA M
|
__asm ORA M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; _a = ORL ; #end, #fp_rc
|
T2 = _a ; _a = ORL ; #end, #fp_rc, #clr_acy
|
|
|
|
|
__code "10111110"
|
__code "10111110"
|
__asm CMP M
|
__asm CMP M
|
|
|
JSR read_m
|
JSR read_m
|
T2 = _a ; DO = SUB ; #end, #fp_rc
|
T2 = _a ; DO = SUB ; #end, #fp_rc
|
|
|
|
|
__code "00ddd100"
|
__code "00ddd100"
|
__asm INR {d}
|
__asm INR {d}
|
|
|
T1 = {d} ; {d} = ADC ; #auxcy, #setacy, #fp_r
|
T1 = {d} ; {d} = ADC ; #auxcy, #setacy, #fp_r
|
NOP ; NOP ; #end // extra line, flag clash
|
NOP ; NOP ; #end // extra line, flag clash
|
|
|
|
|
__code "00110100"
|
__code "00110100"
|
__asm INR M
|
__asm INR M
|
|
|
JSR read_m
|
JSR read_m
|
NOP ; DO = ADC ; #auxcy, #setacy, #fp_r
|
NOP ; DO = ADC ; #auxcy, #setacy, #fp_r
|
JSR write_m
|
JSR write_m
|
|
|
|
|
__code "00ddd101"
|
__code "00ddd101"
|
__asm DCR {d}
|
__asm DCR {d}
|
|
|
T2 = {d} ; {d} = SBB ; #auxcy, #setacy, #fp_r
|
T2 = {d} ; {d} = SBB ; #auxcy, #setacy, #fp_r
|
NOP ; NOP ; #end // extra line, flag clash
|
NOP ; NOP ; #end // extra line, flag clash
|
|
|
|
|
__code "00110101"
|
__code "00110101"
|
__asm DCR M
|
__asm DCR M
|
|
|
JSR read_m // T1 = _x = (HL); but we need it in T2!
|
JSR read_m // T1 = _x = (HL); but we need it in T2!
|
NOP ; NOP ; #clrt1 // flag clash
|
NOP ; NOP ; #clrt1 // flag clash
|
T2 = _x ; DO = SBB ; #auxcy, #setacy, #fp_r
|
T2 = _x ; DO = SBB ; #auxcy, #setacy, #fp_r
|
JSR write_m
|
JSR write_m
|
|
|
|
|
__code "00pp0011"
|
__code "00pp0011"
|
__asm INX [p]
|
__asm INX [p]
|
|
|
T1 = {p}1 ; {p}1 = ADC ; #auxcy, #setacy
|
T1 = {p}1 ; {p}1 = ADC ; #auxcy, #setacy
|
T1 = {p}0 ; {p}0 = ADC ; #end, #auxcy
|
T1 = {p}0 ; {p}0 = ADC ; #end, #auxcy
|
|
|
|
|
__code "00pp1011"
|
__code "00pp1011"
|
__asm DCX [p]
|
__asm DCX [p]
|
|
|
T2 = {p}1 ; {p}1 = SBB ; #auxcy, #setacy // T2 because SUB -> T2 - T1
|
T2 = {p}1 ; {p}1 = SBB ; #auxcy, #setacy // T2 because SUB -> T2 - T1
|
T2 = {p}0 ; {p}0 = SBB ; #end, #auxcy
|
T2 = {p}0 ; {p}0 = SBB ; #end, #auxcy
|
|
|
|
|
__code "00pp1001"
|
__code "00pp1001"
|
__asm DAD [p]
|
__asm DAD [p]
|
|
|
T2 = {p}1 ; NOP
|
T2 = {p}1 ; NOP
|
T1 = _l ; _l = ADD ; #fp_c // we need this cy
|
T1 = _l ; _l = ADD ; #fp_c // we need this cy
|
T2 = {p}0 ; NOP ;
|
T2 = {p}0 ; NOP ;
|
T1 = _h ; _h = ADC ; #end, #fp_c
|
T1 = _h ; _h = ADC ; #end, #fp_c
|
|
|
|
|
__code "00100111"
|
__code "00100111"
|
__asm DAA
|
__asm DAA
|
|
|
// DAA result is only valid after the 2nd cycle;
|
// DAA result is only valid after the 2nd cycle;
|
T1 = _a ; DO = DAA ; //DO value ignored
|
T1 = _a ; DO = DAA ; //DO value ignored
|
T1 = _a ; _a = DAA ; #end, #fp_rc
|
T1 = _a ; _a = DAA ; #end, #fp_rc
|
|
|
|
|
__code "00000111"
|
__code "00000111"
|
__asm RLC
|
__asm RLC
|
|
|
T1 = _a ; _a = rla ; #end, #fp_c
|
T1 = _a ; _a = rla ; #end, #fp_c
|
|
|
|
|
__code "00001111"
|
__code "00001111"
|
__asm RRC
|
__asm RRC
|
|
|
T1 = _a ; _a = rra ; #end, #fp_c
|
T1 = _a ; _a = rra ; #end, #fp_c
|
|
|
|
|
__code "00010111"
|
__code "00010111"
|
__asm RAL
|
__asm RAL
|
|
|
T1 = _a ; _a = rlca ; #end, #fp_c
|
T1 = _a ; _a = rlca ; #end, #fp_c
|
|
|
|
|
__code "00011111"
|
__code "00011111"
|
__asm RAR
|
__asm RAR
|
|
|
T1 = _a ; _a = rrca ; #end, #fp_c
|
T1 = _a ; _a = rrca ; #end, #fp_c
|
|
|
|
|
__code "00101111"
|
__code "00101111"
|
__asm CMA
|
__asm CMA
|
|
|
T1 = _a ; _a = NOT ; #end
|
T1 = _a ; _a = NOT ; #end
|
|
|
|
|
__code "00111111"
|
__code "00111111"
|
__asm CMC
|
__asm CMC
|
|
|
NOP ; cpc ; #end, #fp_c
|
NOP ; cpc ; #end, #fp_c
|
|
|
|
|
__code "00110111"
|
__code "00110111"
|
__asm STC
|
__asm STC
|
|
|
NOP ; sec ; #end, #fp_c
|
NOP ; sec ; #end, #fp_c
|
|
|
|
|
__code "11000011"
|
__code "11000011"
|
__asm JMP addr
|
__asm JMP addr
|
|
|
JSR read_imm_wz
|
JSR read_imm_wz
|
:jmp_addr
|
:jmp_addr
|
T1 = _z ; NOP
|
T1 = _z ; NOP
|
NOP ; _pl = T1
|
NOP ; _pl = T1
|
T1 = _w ; NOP
|
T1 = _w ; NOP
|
NOP ; _ph = T1 ; #end
|
NOP ; _ph = T1 ; #end
|
|
|
|
|
|
|
__code "00000000"
|
__code "00000000"
|
__asm NOP
|
__asm NOP
|
|
|
NOP ; NOP ; #end
|
NOP ; NOP ; #end
|
|
|
|
|
__code "11ccc010"
|
__code "11ccc010"
|
__asm {JZ,JNZ,JC,JNC,JPO,JPE,JP,JM} addr
|
__asm {JZ,JNZ,JC,JNC,JPO,JPE,JP,JM} addr
|
|
|
JSR read_imm_wz
|
JSR read_imm_wz
|
TJSR jmp_addr // TJSR does the JSR or does #end the instruction.
|
TJSR jmp_addr // TJSR does the JSR or does #end the instruction.
|
|
|
|
|
__code "11001101"
|
__code "11001101"
|
__asm CALL addr
|
__asm CALL addr
|
|
|
//:call_addr
|
//:call_addr
|
JSR read_imm_wz
|
JSR read_imm_wz
|
:call_addr //@@
|
:call_addr //@@
|
T1 = _ph ; DO = T1 ; #clrt1
|
T1 = _ph ; DO = T1 ; #clrt1
|
JSR push
|
JSR push
|
T1 = _pl ; DO = T1 ; #clrt1
|
T1 = _pl ; DO = T1 ; #clrt1
|
JSR push
|
JSR push
|
T1 = _z ; NOP
|
T1 = _z ; NOP
|
NOP ; _pl = T1
|
NOP ; _pl = T1
|
T1 = _w ; NOP
|
T1 = _w ; NOP
|
NOP ; _ph = T1 ; #end
|
NOP ; _ph = T1 ; #end
|
|
|
|
|
|
|
__code "11ccc100"
|
__code "11ccc100"
|
__asm {CZ,CNZ,CC,CNC,CPO,CPE,CP,CM} addr
|
__asm {CZ,CNZ,CC,CNC,CPO,CPE,CP,CM} addr
|
|
|
JSR read_imm_wz // skip next 2 bytes
|
JSR read_imm_wz // skip next 2 bytes
|
TJSR call_addr // TJSR does the JSR or does #end the instruction.
|
TJSR call_addr // TJSR does the JSR or does #end the instruction.
|
|
|
|
|
__code "11001001"
|
__code "11001001"
|
__asm RET
|
__asm RET
|
|
|
:ret
|
:ret
|
JSR pop
|
JSR pop
|
NOP ; _pl = T1
|
NOP ; _pl = T1
|
JSR pop
|
JSR pop
|
NOP ; _ph = T1 ; #end
|
NOP ; _ph = T1 ; #end
|
|
|
|
|
__code "11ccc000"
|
__code "11ccc000"
|
__asm {RZ,RNZ,RC,RNC,RPO,RPE,RP,RM}
|
__asm {RZ,RNZ,RC,RNC,RPO,RPE,RP,RM}
|
|
|
|
|
TJSR ret // TJSR does the JSR or does #end the instruction.
|
TJSR ret // TJSR does the JSR or does #end the instruction.
|
|
|
|
|
|
|
__code "11nnn111"
|
__code "11nnn111"
|
__asm {RST 0h,RST 8h,RST 10h,RST 18h,RST 20h,RST 28h,RST 30h,RST 38h}
|
__asm {RST 0h,RST 8h,RST 10h,RST 18h,RST 20h,RST 28h,RST 30h,RST 38h}
|
|
|
T1 = _ph ; DO = T1 ; #clrt1
|
T1 = _ph ; DO = T1 ; #clrt1
|
JSR push
|
JSR push
|
T1 = _pl ; DO = T1 ; #clrt1
|
T1 = _pl ; DO = T1 ; #clrt1
|
JSR push
|
JSR push
|
NOP ; _pl = rst ; #clrt1
|
NOP ; _pl = rst ; #clrt1
|
NOP ; _ph = AND ; #end // T1 & T2 = 0, because T2=0
|
NOP ; _ph = AND ; #end // T1 & T2 = 0, because T2=0
|
// No extra cycle needed, _ph is not used in the next microinstruction
|
// No extra cycle needed, _ph is not used in the next microinstruction
|
|
|
__code "11101001"
|
__code "11101001"
|
__asm PCHL
|
__asm PCHL
|
|
|
T1 = _l ; NOP
|
T1 = _l ; NOP
|
NOP ; _pl = T1
|
NOP ; _pl = T1
|
T1 = _h ; NOP
|
T1 = _h ; NOP
|
NOP ; _ph = T1 ; #end
|
NOP ; _ph = T1 ; #end
|
|
|
|
|
__code "11pp0101" //Except for PUSH PSW
|
__code "11pp0101" //Except for PUSH PSW
|
__asm PUSH [p]
|
__asm PUSH [p]
|
|
|
T1 = {p}0 ; DO = T1 ; #clrt1 // H first...
|
T1 = {p}0 ; DO = T1 ; #clrt1 // H first...
|
JSR push
|
JSR push
|
T1 = {p}1 ; DO = T1 ; #clrt1 // ...L last
|
T1 = {p}1 ; DO = T1 ; #clrt1 // ...L last
|
JSR push
|
JSR push
|
NOP ; NOP ; #end
|
NOP ; NOP ; #end
|
|
|
|
|
__code "11110101"
|
__code "11110101"
|
__asm PUSH PSW
|
__asm PUSH PSW
|
|
|
T1 = _a ; DO = T1 ; #clrt1
|
T1 = _a ; DO = T1 ; #clrt1
|
JSR push
|
JSR push
|
NOP ; DO = PSW ; #clrt1
|
NOP ; DO = PSW ; #clrt1
|
JSR push
|
JSR push
|
NOP ; NOP ; #end
|
NOP ; NOP ; #end
|
|
|
|
|
__code "11pp0001" //Except for POP PSW
|
__code "11pp0001" //Except for POP PSW
|
__asm POP [p]
|
__asm POP [p]
|
|
|
JSR pop
|
JSR pop
|
NOP ; {p}1 = T1
|
NOP ; {p}1 = T1
|
JSR pop
|
JSR pop
|
NOP ; {p}0 = T1 ; #end
|
NOP ; {p}0 = T1 ; #end
|
|
|
|
|
__code "11110001"
|
__code "11110001"
|
__asm POP PSW
|
__asm POP PSW
|
|
|
JSR pop
|
JSR pop
|
NOP ; _f = T1 ; #fp_rc //F<-(SP); F f-fs load automatically
|
NOP ; _f = T1 ; #fp_rc //F<-(SP); F f-fs load automatically
|
JSR pop
|
JSR pop
|
NOP ; _a = T1 ; #end
|
NOP ; _a = T1 ; #end
|
|
|
|
|
__code "11100011"
|
__code "11100011"
|
__asm XTHL
|
__asm XTHL
|
|
|
JSR pop
|
JSR pop
|
NOP ; _z = T1
|
NOP ; _z = T1
|
JSR pop
|
JSR pop
|
NOP ; _w = T1
|
NOP ; _w = T1
|
T1 = _h ; DO = T1 ; #clrt1
|
T1 = _h ; DO = T1 ; #clrt1
|
JSR push
|
JSR push
|
T1 = _l ; DO = T1 ; #clrt1
|
T1 = _l ; DO = T1 ; #clrt1
|
JSR push
|
JSR push
|
T1 = _z ; NOP
|
T1 = _z ; NOP
|
NOP ; _l = T1
|
NOP ; _l = T1
|
T1 = _w ; NOP
|
T1 = _w ; NOP
|
NOP ; _h = T1 ; #end
|
NOP ; _h = T1 ; #end
|
|
|
|
|
__code "11111001"
|
__code "11111001"
|
__asm SPHL
|
__asm SPHL
|
|
|
T1 = _l ; NOP
|
T1 = _l ; NOP
|
NOP ; _sl = T1
|
NOP ; _sl = T1
|
T1 = _h ; NOP
|
T1 = _h ; NOP
|
NOP ; _sh = T1 ; #end
|
NOP ; _sh = T1 ; #end
|
|
|
|
|
__code "11111011"
|
__code "11111011"
|
__asm EI
|
__asm EI
|
|
|
NOP ; NOP ; #ei, #end
|
NOP ; NOP ; #ei, #end
|
|
|
|
|
__code "11110011"
|
__code "11110011"
|
__asm DI
|
__asm DI
|
|
|
NOP ; NOP ; #di, #end
|
NOP ; NOP ; #di, #end
|
|
|
|
|
__code "11011011"
|
__code "11011011"
|
__asm IN port
|
__asm IN port
|
|
|
NOP ; _w = T1 // _w = 0
|
NOP ; _w = T1 // _w = 0
|
JSR read_imm // T1 = port
|
JSR read_imm // T1 = port
|
NOP ; _z = T1 // #ld_al reads from mux...
|
NOP ; _z = T1 // #ld_al reads from mux...
|
NOP ; NOP
|
NOP ; NOP
|
T1 = _z ; NOP ; #ld_al
|
T1 = _z ; NOP ; #ld_al
|
T1 = _w ; NOP ; #ld_addr, #rd, #io
|
T1 = _w ; NOP ; #ld_addr, #rd, #io
|
T1 = DI ; _a = T1 ; #end
|
T1 = DI ; _a = T1 ; #end
|
|
|
|
|
// Can be reduced to 11 states by removing 1st uinst
|
// Can be reduced to 11 states by removing 1st uinst
|
// Then, _b might be put on high addr byte as in the original...
|
// Then, _b might be put on high addr byte as in the original...
|
__code "11010011"
|
__code "11010011"
|
__asm OUT port
|
__asm OUT port
|
|
|
|
|
NOP ; _w = T1 // _w = 0, put on high byte of io address
|
NOP ; _w = T1 // _w = 0, put on high byte of io address
|
JSR read_imm // T1 = port
|
JSR read_imm // T1 = port
|
NOP ; _z = T1 // #ld_al reads from mux...
|
NOP ; _z = T1 // #ld_al reads from mux...
|
T1 = _a ; DO = T1
|
T1 = _a ; DO = T1
|
T1 = _z ; NOP ; #ld_al
|
T1 = _z ; NOP ; #ld_al
|
T1 = _w ; NOP ; #ld_addr, #wr, #io
|
T1 = _w ; NOP ; #ld_addr, #wr, #io
|
NOP ; NOP ; #end
|
NOP ; NOP ; #end
|
|
|
|
|
__code "01110110"
|
__code "01110110"
|
__asm HLT
|
__asm HLT
|
//TODO doc: #halt has to be in the same cycle as #end
|
//TODO doc: #halt has to be in the same cycle as #end
|
NOP ; NOP ; #halt, #end
|
NOP ; NOP ; #halt, #end
|
|
|
|
|
|
|
|
|
//********************************************
|
//********************************************
|
|
|
// T1 = (HL)
|
// T1 = (HL)
|
|
|
:read_m
|
:read_m
|
|
|
T1 = _l ; NOP ; #ld_al
|
T1 = _l ; NOP ; #ld_al
|
T1 = _h ; NOP ; #ld_addr, #rd
|
T1 = _h ; NOP ; #ld_addr, #rd
|
T1 = DI ; _x = T1 ; #ret
|
T1 = DI ; _x = T1 ; #ret
|
|
|
// (HL) = DO, does not return
|
// (HL) = DO, does not return
|
// TODO extra uinst is for wait state, which is not implemented
|
// TODO extra uinst is for wait state, which is not implemented
|
|
|
:write_m
|
:write_m
|
|
|
T1 = _l ; NOP ; #ld_al
|
T1 = _l ; NOP ; #ld_al
|
T1 = _h ; NOP ; #ld_addr, #wr
|
T1 = _h ; NOP ; #ld_addr, #wr
|
NOP ; NOP ; #end
|
NOP ; NOP ; #end
|
|
|
|
|
// T1 = (PC++), DO = T1
|
// T1 = (PC++), DO = T1
|
// T2 must be 0 on entry
|
// T2 must be 0 on entry
|
:read_imm
|
:read_imm
|
|
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
T1 = DI ; DO = T1 ; #ret
|
T1 = DI ; DO = T1 ; #ret
|
|
|
|
|
// T1 = (WZ)
|
// T1 = (WZ)
|
|
|
:read_wz
|
:read_wz
|
|
|
T1 = _z ; NOP ; #ld_al
|
T1 = _z ; NOP ; #ld_al
|
T1 = _w ; NOP ; #ld_addr, #rd
|
T1 = _w ; NOP ; #ld_addr, #rd
|
T1 = DI ; NOP ; #ret
|
T1 = DI ; NOP ; #ret
|
|
|
|
|
// (WZ) = DO, does not return
|
// (WZ) = DO, does not return
|
// TODO extra uinst is for wait state, which is not implemented
|
// TODO extra uinst is for wait state, which is not implemented
|
|
|
:write_wz
|
:write_wz
|
|
|
T1 = _z ; NOP ; #ld_al
|
T1 = _z ; NOP ; #ld_al
|
T1 = _w ; NOP ; #ld_addr, #wr
|
T1 = _w ; NOP ; #ld_addr, #wr
|
NOP ; NOP ; #end
|
NOP ; NOP ; #end
|
|
|
// T1 = (RP)
|
// T1 = (RP)
|
|
|
:read_p
|
:read_p
|
|
|
T1 = {p}1 ; NOP ; #ld_al
|
T1 = {p}1 ; NOP ; #ld_al
|
T1 = {p}0 ; NOP ; #ld_addr, #rd
|
T1 = {p}0 ; NOP ; #ld_addr, #rd
|
T1 = DI ; NOP ; #ret
|
T1 = DI ; NOP ; #ret
|
|
|
|
|
// (RP) = DO, does not return
|
// (RP) = DO, does not return
|
// TODO extra uinst is for wait state, which is not implemented
|
// TODO extra uinst is for wait state, which is not implemented
|
|
|
:write_p
|
:write_p
|
|
|
T1 = {p}1 ; NOP ; #ld_al
|
T1 = {p}1 ; NOP ; #ld_al
|
T1 = {p}0 ; NOP ; #ld_addr, #wr
|
T1 = {p}0 ; NOP ; #ld_addr, #wr
|
NOP ; NOP ; #end
|
NOP ; NOP ; #end
|
|
|
// WZ = imm16
|
// WZ = imm16
|
|
|
:read_imm_wz
|
:read_imm_wz
|
|
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
T1 = DI ; _z = T1
|
T1 = DI ; _z = T1
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _pl ; _pl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
T1 = _ph ; _ph = ADC ; #ld_addr, #rd, #auxcy
|
T1 = DI ; _w = T1 ; #ret
|
T1 = DI ; _w = T1 ; #ret
|
|
|
// push DO
|
// push DO
|
// no wait cycle!
|
// no wait cycle!
|
|
|
:push
|
:push
|
T2 = _sl ; _sl = SBB ; #auxcy, #setacy
|
T2 = _sl ; _sl = SBB ; #auxcy, #setacy
|
T2 = _sh ; _sh = SBB ; #auxcy
|
T2 = _sh ; _sh = SBB ; #auxcy
|
T1 = _sl ; NOP ; #ld_al
|
T1 = _sl ; NOP ; #ld_al
|
T1 = _sh ; NOP ; #ld_addr, #wr,
|
T1 = _sh ; NOP ; #ld_addr, #wr,
|
NOP ; NOP ; #ret // extra line, flag clash
|
NOP ; NOP ; #ret // extra line, flag clash
|
|
|
|
|
// POP T1
|
// POP T1
|
|
|
:pop
|
:pop
|
T1 = _sl ; _sl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _sl ; _sl = ADC ; #ld_al, #auxcy, #setacy
|
T1 = _sh ; _sh = ADC ; #ld_addr, #rd, #auxcy
|
T1 = _sh ; _sh = ADC ; #ld_addr, #rd, #auxcy
|
T1 = DI ; NOP ; #ret // extra line, flag clash
|
T1 = DI ; NOP ; #ret // extra line, flag clash
|
|
|
|
|
|
|