/* ucode.txt - The contents of the microcode rom for the 9086 CPU

   This file is part of the 9086 project.

   Copyright (c) 2024 Efthymios Kritikos

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

//mas: MemIo Address Select
//        0: register file output  1: alu output
//
//wbo: Wbit overwrite, {VALUE,ENABLE}. ex 11 would force one, 10 wouldn't do anything
//
//krs: Keep registers, selects weather the register port 1 and/or 2
//     addresses is set on that microcoded instruction or kept as it
//     was before allowing for registers to be parameterised.
//       {Register_write_port,Register_port2, Register_port1}
//
//rr2: reg_read_port2_addr
//
//imd: IN_MOD
//
//rr1: reg_read_port1_addr
//
//a1f: ALU 1 operation (function)
//    000:ALU_OP_ADD
//    001:ALU_OP_SUB
//    010:ALU_OP_AND
//    011:ALU_OP_OR
//    100:ALU_OP_XOR
//    101:ALU_OP_ADD_SIGNED_B
//    110:ALU_OP_SUB_REVERSE
//    111:ALU_OP_SHIFT_LEFT
//
//a1o: OUT_MOD. Handled in `PROC_EX_STATE_ENTRY
//
//a12: In ALU 1 sel 2
//
//a11: In ALU 1 sel 1
//
//rwa: Register Write Address
//
//nxs: Next State
//    000: PROC_EX_STATE_ENTRY
//    001: PROC_DE_LOAD_16_PARAM
//    010: PROC_DE_LOAD_8_PARAM
//    011: PROC_MEMIO_READ
//    100: PROC_MEMIO_READ_SETADDR (used when addressing based on ALU_OUT
//
//Nxt M: Next microcode address


//   39  38  36  33   29  26   22  19  16  14  12   8   5    0
// INT
//   mas|wbo|krs|rr2 |imd|rr1 |a1f|a1o|a12|a11|rwa |nxs|Nxt M |
@00c __0__00_000_0000_011_1100_001_011__00__01_1100_010_001101 // ALU_1: SP           ALU_2: PARAM2 (2) ALU_OP:SUB  ALU_out: SP   (also fetch the opcode argument to PARAM1)
@00d __0__00_000_0000_011_xxxx_000_110__10__11_xxxx_000_001110 // ALU_1: 0            ALU_2: PC         ALU_OP:ADD  ALU_out: [SP]
/* We read the parameter and get the address to jump on ALU_OUT */
@00e __0__00_000_xxxx_011_xxxx_111_111__00__00_xxxx_000_001111 // ALU_1: PARAM1 (arg)                 ALU_2: PARAM2 (2)       ALU_OP:SHIFT ALU_out: PARAM1
@00f __1__00_000_xxxx_011_xxxx_000_100__00__00_xxxx_100_010000 // ALU_1: PARAM1 (base int table addr) ALU_2: PARAM2 (2)       ALU_OP:ADD ALU_out: NULL
@010 __0__00_000_xxxx_011_xxxx_000_101__00__11_xxxx_000_000000 // ALU_1: 0            ALU_2: PARAM2 (address) ALU_OP:SHIFT ALU_out: PC

// POP
//   mas|wbo|krs|rr2 |imd|rr1 |a1f|a1o|a12|a11|rwa |nxs|Nxt M |
@00a __0__00_100_0000_110_xxxx_011_011__00__11_xxxx_011_001011 // ALU_1: 0           ALU_2: PARAM2 ([SP])    ALU_OP:ADD   ALU_out: REG
@00b __0__00_000_1100_011_0000_000_011__01__00_1100_000_000000 // ALU_1: PARAM1 (2)  ALU_2: SP               ALU_OP:ADD   ALU_out: SP

// PUSH
//   mas|wbo|krs|rr2 |imd|rr1 |a1f|a1o|a12|a11|rwa |nxs|Nxt M |
@008 __0__00_010_0000_011_1100_001_011__00__01_1100_000_001001 // ALU_1: SP  ALU_2: PARAM2 (2) ALU_OP:SUB  ALU_out: SP   (also fetch the opcode argument to PARAM1)
@009 __0__00_010_0000_011_xxxx_000_110__01__11_xxxx_000_000000 // ALU_1: 0   ALU_2: REG        ALU_OP:ADD  ALU_out: [SP]

// STOS
//   mas|wbo|krs|rr2 |imd|rr1 |a1f|a1o|a12|a11|rwa |nxs|Nxt M |
@006 __0__00_000_1000_011_xxxx_000_000__01__11_xxxx_000_000111 // ALU_1: 0   ALU_2: AX           ALU_OP:ADD  ALU_out: [DI]
@007 __0__11_000_xxxx_011_1111_000_011__00__01_1111_000_000000 // ALU_1: DI  ALU_2: PARAM2 (2)   ALU_OP:ADD  ALU_OUT: DI

// RET
//   mas|wbo|krs|rr2 |imd|rr1 |a1f|a1o|a12|a11|rwa |nxs|Nxt M |
@004 __0__00_000_0000_110_xxxx_000_101__00__11_xxxx_011_000101 // ALU_1: 0           ALU_2: PARAM2 ([SP]) ALU_OP:ADD  ALU_out: PC (also read [SP] to PARAM2)
@005 __0__00_000_1100_011_0000_000_011__01__00_1100_000_000000 // ALU_1: PARAM1 (2)  ALU_2: SP            ALU_OP:ADD  ALU_out: SP

// CALL
//   mas|wbo|krs|rr2 |imd|rr1 |a1f|a1o|a12|a11|rwa |nxs|Nxt M |
@001 __0__00_000_0000_011_1100_001_011__00__01_1100_001_000010 // ALU_1: SP           ALU_2: PARAM2 (2) ALU_OP:SUB  ALU_out: SP   (also fetch the opcode argument to PARAM1)
@002 __0__00_000_0000_011_xxxx_000_110__10__11_xxxx_000_000011 // ALU_1: 0            ALU_2: PC         ALU_OP:ADD  ALU_out: [SP]
@003 __0__00_000_0000_011_xxxx_000_101__10__00_xxxx_000_000000 // ALU_1: PARAM1 (arg) ALU_2: PC         ALU_OP:ADD  ALU_out: PC

@000 __0__00_000_0000_000_0000_000_000__00__00_0000_000_000000
