From ecf8227b531ea18fb5e9b13d1f464c8137293d74 Mon Sep 17 00:00:00 2001 From: Marie Date: Wed, 4 Dec 2024 19:52:05 +0100 Subject: [PATCH] add basic mfd0816 site --- build.mb | 26 +- data/index.sad | 6 + data/projects/mfd0816/VERSION1_DESIGN | 568 +++++++++++++++ data/projects/mfd0816/VERSION1_INSTRUCTIONS | 756 ++++++++++++++++++++ data/projects/mfd0816/index.sad | 21 + test.css | 1 - 6 files changed, 1375 insertions(+), 3 deletions(-) create mode 100644 data/projects/mfd0816/VERSION1_DESIGN create mode 100644 data/projects/mfd0816/VERSION1_INSTRUCTIONS create mode 100644 data/projects/mfd0816/index.sad diff --git a/build.mb b/build.mb index 13369ef..13bc53f 100644 --- a/build.mb +++ b/build.mb @@ -9,13 +9,18 @@ end sector targets section static - list str c_rules 'sites' + list str c_rules 'sites', 'symlinks' end end sector c_rules section sites - list str input 'index', 'projects/fpc-sitegen', 'projects/sad', 'projects/mariebuild' + list str input + 'index', + 'projects/fpc-sitegen', + 'projects/sad', + 'projects/mariebuild', + 'projects/mfd0816/index' str input_format 'data/$(%element%).sad' str output_format '$(%element%).html' @@ -36,6 +41,23 @@ sed -i ''s/\\\$\\\$TIME\\\$\\\$/''"\$TIME/g" $(%output%) sed -i ''s@\\\$\\\$BRANCH\\\$\\\$@''"\$BRANCH@g" $(%output%) sed -i ''s@\\\$\\\$SOURCE\\\$\\\$@$(%input%)@g'' $(%output%) sed -i ''s/\\\$\\\$COMMIT\\\$\\\$/''"\$COMMIT_SHORT/g" $(%output%) +' + end + + section symlinks + list str input + 'projects/mfd0816/VERSION1_DESIGN', + 'projects/mfd0816/VERSION1_INSTRUCTIONS' + str input_format 'data/$(%element%)' + str output_format '$(%element%)' + + str exec '#!/usr/bin/env bash +set -e + +mkdir -p \$(dirname $(%output%)) + +rm $(%output%) +ln --symbolic $(%input%) $(%output%) ' end end diff --git a/data/index.sad b/data/index.sad index c909f3e..25e7594 100644 --- a/data/index.sad +++ b/data/index.sad @@ -31,6 +31,12 @@ template this also looks like shit :) * [demo] epoqe - Caturday Night Fever (music)
* [demo] epoqe - Eden Disorder (code support, music)
+{$end-section} +{$begin-section} other +{$sub-head} other + +* mfd0816[github]
+
  A fantasy CPU based on the intel 8088
{$end-section} {$begin-section} c {$sub-head} c diff --git a/data/projects/mfd0816/VERSION1_DESIGN b/data/projects/mfd0816/VERSION1_DESIGN new file mode 100644 index 0000000..607ce16 --- /dev/null +++ b/data/projects/mfd0816/VERSION1_DESIGN @@ -0,0 +1,568 @@ + MFD-0816 TECHNICAL SPECIFACTION & OVERVIEW + November 2024 + +CONTENTS +──────────────────────────────────────────────────────────────────────────────── + + 1..... INTRODUCTION & OVERVIEW + 1.1... PINS + 2..... REGISTERS + 2.1... GENERAL PURPOSE REGISTERS + 2.2... SPECIALIZED REGISTERS + 2.2.1. THE STACK + 2.2.2. FLAGS + 3..... ADDRESSING & THE I/O BUS + 3.1... I/O BUS INSTRUCTIONS + 4..... INSTRUCTION SET OVERVIEW + 4.1... INSTRUCTION ENCODING + 4.1.1. REGISTER IDENTIFICATION + 5..... ADDRESSING MODES + 6..... INTERRUPTS + 6.1... HARDWARE INTERRUPTS + 6.2... SOFTWARE INTERRUPTS + 7..... RESET + ...... LICENSE + +1. INTRODUCTION & OVERVIEW +──────────────────────────────────────────────────────────────────────────────── + + The MFD-0816 is a 16-bit fantasy CPU and based on the intel 8088. + + ► 16-bit address bus + ► 16-bit word + ► 8-bit I/O bus + ► 4x 16-bit general purpose register + +1.1. PINS +──────────────────────────────────────────────────────────────────────────────── + + ┌───────┬────────┬────────────────────────────────────────────────┐ + │ NAME │ PINS │ DESCRIPTION │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ CLK │ 00 │ Clock pin. When high the CPU executes one step │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ AIO │ 01..16 │ 16-bit Memory IO Bus │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ GIO │ 17..24 │ 8-bit IO Bus │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ IRQ │ 25 │ Interrupt Request │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ IRA │ 26 │ Interrupt Acknowledge │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ RESET │ 27 │ Reset │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ AMS │ 28 │ Memory IO Bus Mode Select │ + ├───────┼────────┼────────────────────────────────────────────────┤ + │ GMS │ 29 │ 8-bit IO Bus Mode Select │ + └───────┴────────┴────────────────────────────────────────────────┘ + +2. REGISTERS +2.1. GENERAL PURPOSE REGISTERS +──────────────────────────────────────────────────────────────────────────────── + + The MFD-0816 has 4 16-bit general purpose registers with the following names: + + ► ACL (AH & AL) + ► BCL (BH & BL) + ► CCL (CH & CL) + ► DCL (DH & DL) + + Each general purpose register of the MFD-0816 is usable as either a complete + WORD or as its high and low bytes. + + ┌─────────┐ + │ ACL │ + ├────┬────┤ + │ AH │ AL │ + └────┴────┘ + + The above illustration shows the register "ACL", which can be used as a + complete word with this name, alternatively its high byte can be accessed + with the "AH" name and the low byte using "AL". + +2.2. SPECIALIZED REGISTERS +──────────────────────────────────────────────────────────────────────────────── + + The MFD-0816 has the following specialized registers: + + ► SP (Stack Pointer) + ► IP (Instruction Pointer) + ► AR (Accumulator) + ► FL (Flags) + ► IID (Interrupt ID) + + All of these registers have a size of one word. + + The Stack Pointer register holds the current address of the top of the stack. + + The Instruction Pointer register holds the address of the + current instruction. + + The Accumulator register holds the result of the last arithmetic operation + + The Flags register holds an assortment of different bit flags, elaborated + upon in chapter 2.2.2. Bits can only be set by their respective clear and set + instructions. + + The IID register hold the value of the last interrupt. It can only be set + via an interrupt. + +2.2.1. THE STACK +──────────────────────────────────────────────────────────────────────────────── + + The stack is a memory structure where the first element "pushed" on to it will + be the last element to leave it. In the case of the MFD-0816, one + stack-element is a word. + + In the case of this CPU, the stack grows "downwards" (the address of the top + of the stack gets smaller the larger it gets). This address is held in the + SP register. In case the value of SP is equal to 0 and another element is + "pushed" onto the stack it will cause a CPU exception to be thrown. + + The starting location of the stack is not fixed and must be set when + initializing the CPU. This is simply done by loading the SP register with the + address where the stack should start. Note that this address must always be a + multiple of two. + +2.2.2. FLAGS +──────────────────────────────────────────────────────────────────────────────── + + ┌──────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ + │ BIT │ 0F │ 0E │ 0D │ 0C │ 0B │ 0A │ 09 │ 08 │ 07 │ 06 │ 05 │ 04 │ 03 │ + ├──────┼────┼────┼────┼────┼────┼────┼────┼────┼────┼────┼────┼────┼────┤ + │ NAME │ OF │ CF │ ZF │ NF │ IE │ RT │ RS │ RS │ RS │ RS │ RS │ RS │ RS │ + └──────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ + ┌──────┬────┬────┬────┐ + │ BIT │ 02 │ 01 │ 00 │ + ├──────┼────┼────┼────┤ + │ NAME │ RS │ RS │ RS │ + └──────┴────┴────┴────┘ + + ► OF (Overflow Flag) Set if the last arithmetic operation overflowed. + ► CF (Carry Flag) Set to indicate that an arithmetic carry + has been generated. + ► ZF (Zero Flag) Set to indicate that the last arithmetic operation + resulted in a value equal to 0 in the + accumulator register. + ► NF (Negative Flag) Set if the result of the last arithmetic operation has + its highest (left most) bit set. + ► IE (Interrupt Enable) If set, interrupts are enabled and will be handled. + ► RT (Reset) If set, the processor is in the reset process. + ► RS (Reserved) Bits marked with this name are reserved for + future use. + +3. ADDRESSING & THE I/O BUS +──────────────────────────────────────────────────────────────────────────────── + + The MFD-0816 provides a regular address & data bus mainly used for + loading of instructions and memory. The address bus and its corresponding + data bus are both 16-bits wide. The high-byte of the received data may be + ignored by the CPU if not needed. + + Write Operation: + + T1 ╷ T2 ╷ + CLK ┌──────────────────┐ ┌────────────────────┐ + ──┘ └────────────────────┘ └─ + + AMS ┌────────────────────┐ + ┘ └─────────────────────────────────────────── + 🮣───────────────────🮢 🮣────────────────────🮢 + AIO ─🮤 ADDRESS OUT 🮥────────────────────🮤 DATA OUT 🮥─ + 🮡───────────────────🮠 🮡────────────────────🮠 + + Read Operation: + + T1 ╷ T2 ╷ + CLK ┌──────────────────┐ ┌────────────────────┐ + ──┘ └──────────────────┘ └─ + + AMS ┌────────────────────────────────────────────────────────────┐ + ┘ └─ + 🮣───────────────────🮢 🮣────────────────────🮢 + AIO ─🮤 ADDRESS OUT 🮥──────────────────🮤 DATA IN 🮥─ + 🮡───────────────────🮠 🮡────────────────────🮠 + + ► If AMS is high during T1, the operation is a write opeartion. If AMS is + also hgih during T2, it is a read operation. + ► During T1 the 16-bit address is set. + ► (Write Operation) During T2 the word to be written is set in case of + a write operation. + ► (Write Operation) During T2 the requested data must be set by the peer. + + + An 8-bit I/O bus is also provided for interacting with external hardware + without requiring memory-mapping. + + Write Operation: + + T1 ╷ T2 ╷ T3 ╷ T4 ╷ + CLK ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ + ─┘ └──────┘ └──────┘ └──────┘ └─ + + GMS ┌─────────────────────┐ + ┘ └───────────────────────────── + 🮣────────────────────🮢 🮣────────────────────🮢 + GIO ─🮤 ADDRESS OUT 🮥──────🮤 DATA OUT 🮥─ + 🮡────────────────────🮠 🮡────────────────────🮠 + + Read Operation: + + T1 ╷ T2 ╷ T3 ╷ T4 ╷ + CLK ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ + ─┘ └──────┘ └──────┘ └──────┘ └─ + + GMS + ──────────────────────────────────────────────────── + 🮣────────────────────🮢 🮣────────────────────🮢 + GIO ─🮤 ADDRESS OUT 🮥──────🮤 DATA IN 🮥─ + 🮡────────────────────🮠 🮡────────────────────🮠 + + ► If GMS is high only during T1, the operation is a write opeartion. + If it is also high during T2, it is a read operation. + ► During T1 the high-byte of the 16-bit address is set. + ► During T2 the low-byte of the 16-bit address is set. + ► (Write Operation) During T3 the high-byte of the word is set. + ► (Write Operation) During T4 the low-byte of the word is set. + ► (Read Operation) During T3 the high-byte of the word + must be set by the peer. + ► (Read Operation) During T4 the low-byte of the word + must be set by the peer. + +3.1. I/O BUS INSTRUCTIONS +──────────────────────────────────────────────────────────────────────────────── + + Four instructions for operation on the I/O BUS are provided: + + ► OUT - Write data to the bus + ► IN - Read data from the bus + ► BOT - Write a block of data to the bus + ► BIN - Read a block of data from the bus + +4. INSTRUCTION SET OVERVIEW +──────────────────────────────────────────────────────────────────────────────── + + ┌──────┬──────────────────────────────────┬────────────┐ + │ NAME │ MEANING │ OPCODE(S) │ + ├──────┼──────────────────────────────────┼────────────┤ + │ ADC │ Add with carry │ 0x00 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ ADD │ Add │ 0x01 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ AND │ Logical AND │ 0x02 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ BIN │ Read block of data from I/O │ 0x03 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ BOT │ Write block of data to I/O │ 0x04 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ CALL │ Call subroutine │ 0x05 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ CLf │ Clear flag │ 0x2b..0x3a │ + ├──────┼──────────────────────────────────┼────────────┤ + │ CMP │ Compare operands │ 0x07 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ DEC │ Decrement by 1 │ 0x08 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ DIV │ Unsigned divide │ 0x09 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ IDIV │ Signed divide │ 0x0a │ + ├──────┼──────────────────────────────────┼────────────┤ + │ IMUL │ Signed multiply │ 0x0b │ + ├──────┼──────────────────────────────────┼────────────┤ + │ IN │ Read data from I/O │ 0x0c │ + ├──────┼──────────────────────────────────┼────────────┤ + │ INC │ Increment by 1 │ 0x0d │ + ├──────┼──────────────────────────────────┼────────────┤ + │ INT │ Trigger interrupt │ 0x0e │ + ├──────┼──────────────────────────────────┼────────────┤ + │ IRET │ Return from interrupt │ 0x0f │ + ├──────┼──────────────────────────────────┼────────────┤ + │ Jcc │ Jump (if condition) │ 0x10..0x1a │ + ├──────┼──────────────────────────────────┼────────────┤ + │ LD │ Load word to register │ 0x1b │ + ├──────┼──────────────────────────────────┼────────────┤ + │ MOV │ Mov value between registers │ 0x1c │ + ├──────┼──────────────────────────────────┼────────────┤ + │ MUL │ Unsigned multiply │ 0x1d │ + ├──────┼──────────────────────────────────┼────────────┤ + │ NEG │ Negate │ 0x1e │ + ├──────┼──────────────────────────────────┼────────────┤ + │ NOP │ No operation │ 0x1f │ + ├──────┼──────────────────────────────────┼────────────┤ + │ NOT │ Negate the operand (logical NOT) │ 0x20 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ OR │ Logical OR │ 0x21 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ OUT │ Write data to I/O │ 0x22 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ POP │ Pop data from stack │ 0x23 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ PUSH │ Push data onto stack │ 0x24 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ RET │ Return from subroutine │ 0x25 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ ROL │ Rotate left │ 0x26 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ ROR │ Roate right │ 0x27 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ SL │ Shift left │ 0x28 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ SR │ Shift right │ 0x29 │ + ├──────┼──────────────────────────────────┼────────────┤ + │ ST │ Store word from register │ 0x2a │ + ├──────┼──────────────────────────────────┼────────────┤ + │ STf │ Set flag │ 0x3b..0x4a │ + ├──────┼──────────────────────────────────┼────────────┤ + │ SUB │ Subtraction │ 0x4b │ + ├──────┼──────────────────────────────────┼────────────┤ + │ TEST │ Logical compare (AND) │ 0x4c │ + ├──────┼──────────────────────────────────┼────────────┤ + │ XOR │ Exclusive OR │ 0x4d │ + └──────┴──────────────────────────────────┴────────────┘ + +4.1 INSTRUCTION ENCODING +──────────────────────────────────────────────────────────────────────────────── + + ┌────────┬────────┬───────────────────────────────────────────┐ + │ WORD │ BITS │ USAGE │ + ├────────┼────────┼───────────────────────────────────────────┤ + │ 00 │ 0F..08 │ Identification of the instruction │ + ├────────┼────────┼───────────────────────────────────────────┤ + │ 00 │ 07..04 │ Operand 1 addressing mode │ + ├────────┼────────┼───────────────────────────────────────────┤ + │ 00 │ 03..00 │ Operand 2 addressing mode │ + └────────┴────────┴───────────────────────────────────────────┘ + + The addressing modes are encoded as follows: + + ┌────────┬────────────────────────────┐ + │ VALUE │ MODE │ + ├────────┼────────────────────────────┤ + │ 0000 │ Immediate │ + ├────────┼────────────────────────────┤ + │ 0001 │ Direct │ + ├────────┼────────────────────────────┤ + │ 0010 │ Indirect │ + ├────────┼────────────────────────────┤ + │ 0101 │ Relative Direct │ + ├────────┼────────────────────────────┤ + │ 0110 │ Relative Indirect │ + ├────────┼────────────────────────────┤ + │ 1000 │ Register Immediate │ + ├────────┼────────────────────────────┤ + │ 1001 │ Register Direct │ + ├────────┼────────────────────────────┤ + │ 1010 │ Register Indirect │ + ├────────┼────────────────────────────┤ + │ 1101 │ Register Relative Direct │ + ├────────┼────────────────────────────┤ + │ 1110 │ Register Relative Indirect │ + └────────┴────────────────────────────┘ + + The highest bit (bit 03) is reffered to as the register bit. If high, + the operand's immediate value identifies a register. + + The second highest bit (bit 02) is the relative bit. If high, + the operands value is relative to the value of the IP register. + + The second lowest bit (bit 01) is the indirect bit. If high, + the value behind the operand is another address which must be read from. + + The lowest bit (bit 00) is the direct bit. If high, + the operand is an address pointing towards the actual value to be worked + with. + + Bits 00 and 01 should not be set at the same time. Should the CPU encounter + this, an exception will be raised. + + Bit 02 has no effect if neither Bit 01 or Bit 00 are high. + +4.1.1. REGISTER IDENTIFICATION +──────────────────────────────────────────────────────────────────────────────── + + In case the register bit is set for a specific operand, the immediate value + is only one byte long. The register is encoded as follows: + + ┌─────┬───────┐ + │ REG │ VALUE │ + ├─────┼───────┤ + │ AL │ 0x00 │ + ├─────┼───────┤ + │ AH │ 0x01 │ + ├─────┼───────┤ + │ ACL │ 0x02 │ + ├─────┼───────┤ + │ BL │ 0x03 │ + ├─────┼───────┤ + │ BH │ 0x04 │ + ├─────┼───────┤ + │ BCL │ 0x05 │ + ├─────┼───────┤ + │ CL │ 0x06 │ + ├─────┼───────┤ + │ CH │ 0x07 │ + ├─────┼───────┤ + │ CCL │ 0x08 │ + ├─────┼───────┤ + │ DL │ 0x09 │ + ├─────┼───────┤ + │ DH │ 0x0a │ + ├─────┼───────┤ + │ DCL │ 0x0b │ + ├─────┼───────┤ + │ SP │ 0x0c │ + ├─────┼───────┤ + │ IP │ 0x0d │ + ├─────┼───────┤ + │ AR │ 0x0e │ + ├─────┼───────┤ + │ FL │ 0x0f │ + ├─────┼───────┤ + │ IID │ 0x10 │ + └─────┴───────┘ + +5. ADDRESSING MODES +──────────────────────────────────────────────────────────────────────────────── + + Addressing modes define how instructions access operands. There are three + primary modes: Immediate, Direct, and Indirect. + + In Immediate Addressing, the operand is either a literal value or a + register value. For example, in the instruction "MOV #64, AL", the immediate + value 64 is assigned directly to the register AL, making AL equal to 64. + + ┌─────────────┬─────────┐ + │ INSTRUCTION │ OPERAND │ + └─────────────┴─────────┘ + IMMEDIATE ADDRESSING + + In Direct Addressing, the operand specifies an address where the actual + value is stored. The instruction accesses the value directly from + this address. + + ┌─────────────┬───────────────────┐ ┌───────┐ + │ INSTRUCTION │ OPERAND (ADDRESS) ├────────►│ VALUE │ + └─────────────┴───────────────────┘ └───────┘ + DIRECT ADDRESSING + + Indirect Addressing also uses an address as the operand, but instead of + pointing directly to the value, the address points to another address + where the final value is stored. This requires an extra level of indirection. + + ┌─────────────┬───────────────────┐ ┌────────────────────────────┐ + │ INSTRUCTION │ OPERAND (ADDRESS) ├────────►│ POINTER TO VALUE (ADDRESS) ├─┐ + └─────────────┴───────────────────┘ ├────────────────────────────┤ │ + INDIRECT ADDRESSING │ VALUE │◄┘ + └────────────────────────────┘ + + Direct and Indirect modes typically use absolute addresses. However, they can + also operate in Relative Addressing mode, where the address is calculated + relative to the current value of the Instruction Pointer (IP) register. + + ► To reference a memory location before the current IP value, + the highest bit of the address must be set, indicating a negative offset. + +6. INTERRUPTS +──────────────────────────────────────────────────────────────────────────────── + + Interrupts can be triggered by the INT instruction or the INT-Pin being pulled + high. + + Both types of interrupts share this behaviour after acquiring the interrupt + id. + + 1. Save the value of the IP register to the top of the stack + 2. Load the value from the interrupt vector into the IP register. + The interrupt vector is located at address 0xfffc + 3. Clear the IE flag + 4. Continue execution + + After handling of an interrupt is done, the IRET instruction must be invoked. + This does the following: + + 1. Set the IE flag + 2. Load the value from the top of the stack into the IP register + 3. continue execution + +6.1. HARDWARE INTERRUPTS +──────────────────────────────────────────────────────────────────────────────── + + Hardware interrupts consist of two sequences: The Interrupt request and the + Interrupt Acknowledge sequence. + + Interrupt request: + + T1 ╷ + CLK ┐ ┌──────┐ ┌ + └──────┘ └──────┘ + + IRQ ┌──────┐ + ───────┘ └─────── + + The CPU checks if the IRQ line is high at the ench of each clock cycle. So if + IRQ is high at the end of T1, an interrupt was requested. After this sequence, + the Acknowledge sequence is entered. + + Interrupt acknowledge: + + T1 ╷ T2 ╷ + CLK ┐ ┌─────────┐ ┌─────────┐ + └─────────┘ └─────────┘ └─ + + IRA ┌─────────────────────────────┐ + ──────────┘ └─ + + 🮣──────────🮢 + GIO ─────────────────────────────🮤 DATA IN 🮥─ + 🮡──────────🮠 + + As soon as the CPU is ready, it will set the IRA line high for two clock + pulses. During the first pulse, nothing else happens. During the second pulse + the CPU reads a byte of whatever data currently is on the I/O Bus. This data + is used as the interrupt id and written to the IID register. + + After both sequences are completed, the CPU continues with the shared + behaviour specified in chapter 6. + +6.1. SOFTWARE INTERRUPTS +──────────────────────────────────────────────────────────────────────────────── + + Software interrupts are a lot simpler. They are triggered by an INT + instruction. + + When an INT instruction is encountered, the CPU first sets the IID register + to the value of the first operand of the instruction. + + After this is completed, the CPU continues with the shared + behaviour specified in chapter 6. + +7. RESET +──────────────────────────────────────────────────────────────────────────────── + + The CPU can be reset to start execution from the reset vector. The reset + vector is located at address 0xfffe. + + T1 ╷ T2 ╷ T3 ╷ + CLK ┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ + └─────────┘ └─────────┘ └─────────┘ └ + + RESET ┌─────────┐ + ──────────┘ └──────────────────────────────────────── + + In order to execute a reset, the RESET pin must be high at the end of a + clock pulse. If reset is high for longer than this, it will continually reset + the processor. + + After a reset has been triggered, the RT flag is set and the next few cycles + are used to read the value of the reset vector into the IP register. + Afterwards, the RT flag is cleared and the processor resumes execution. + + Note that resetting does not clear any registers or memories except for the + FL register. Interrupts also have no effect whilst resetting, regardless of + the state of the IE flag. + +LICENSE +──────────────────────────────────────────────────────────────────────────────── + + MFD0816 DESIGN by Marie Eckert is licensed under CC BY-SA 4.0, + see diff --git a/data/projects/mfd0816/VERSION1_INSTRUCTIONS b/data/projects/mfd0816/VERSION1_INSTRUCTIONS new file mode 100644 index 0000000..5d637a1 --- /dev/null +++ b/data/projects/mfd0816/VERSION1_INSTRUCTIONS @@ -0,0 +1,756 @@ + MFD-0816 INSTRUCTION SET REFERENCE + November 2024 + +CONTENTS +──────────────────────────────────────────────────────────────────────────────── + + 1.... INSTRUCTION LISTING + 2.... INSTRUCTION SPECIFICATIONS + ..... LICENSE + +1. INSTRUCTION LISTING +──────────────────────────────────────────────────────────────────────────────── + + 0x00..0x0f + ‾‾‾‾‾‾‾‾‾‾ + ┌──────┬─────────────┬─────────────────────────┐ + │ CODE │ NAME(S) │ DESCRIPTION │ + ├──────┼─────────────┼─────────────────────────┤ + │ 0x00 │ ADC │ Add with carry │ + │ 0x01 │ ADD │ Add │ + │ 0x02 │ AND │ Logical AND │ + │ 0x03 │ BIN │ Read block from I/O Bus │ + │ 0x04 │ BOT │ Write block to I/O Bus │ + │ 0x05 │ CALL │ Call subroutine │ + │ 0x06 │ │ Reserved │ + │ 0x07 │ CMP │ Compare operands │ + │ 0x08 │ DEC │ Decrement by 1 │ + │ 0x09 │ DIV │ Unsigned divide │ + │ 0x0a │ IDIV │ Signed divide │ + │ 0x0b │ IMUL │ Signed multiply │ + │ 0x0c │ IN │ Read byte from I/O Bus │ + │ 0x0d │ INC │ Increment by 1 │ + │ 0x0e │ INT │ Trigger interrupt │ + │ 0x0f │ IRET │ Return from interrupt │ + └──────┴─────────────┴─────────────────────────┘ + + Jcc - Jump (if condition is met) + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + ┌──────┬─────────────┬─────────────────────────┐ + │ CODE │ NAME(S) │ DESCRIPTION │ + ├──────┼─────────────┼─────────────────────────┤ + │ 0x10 │ JMP │ Jump │ + │ 0x11 │ JZ/JE │ Jump if ZF=1 │ + │ 0x12 │ JG │ Jump if ZF=0 and NF=OF │ + │ 0x13 │ JGE │ Jump if NF=OF │ + │ 0x14 │ JL │ Jump if NF<>OF │ + │ 0x15 │ JLE │ Jump if ZF=1 or NF<>OF │ + │ 0x16 │ JC │ Jump if CF=1 │ + │ 0x17 │ JS │ Jump if NF=1 │ + │ 0x18 │ JNZ/JNE │ Jump if ZF=0 │ + │ 0x19 │ JNC │ Jump if CF=0 │ + │ 0x1a │ JNS │ Jump if NF=0 │ + └──────┴─────────────┴─────────────────────────┘ + + 0x1b..0x2a + ‾‾‾‾‾‾‾‾‾‾ + ┌──────┬─────────────┬─────────────────────────┐ + │ CODE │ NAME(S) │ DESCRIPTION │ + ├──────┼─────────────┼─────────────────────────┤ + │ 0x1b │ LD │ Load word into register │ + │ 0x1c │ MOV │ Move between registers │ + │ 0x1d │ MUL │ Unsigned multiply │ + │ 0x1e │ NEG │ Negate │ + │ 0x1f │ NOP │ No operation │ + │ 0x20 │ NOT │ Negate operand (logical)│ + │ 0x21 │ OR │ Logical OR │ + │ 0x22 │ OUT │ Write byte to I/O Bus │ + │ 0x23 │ POP │ Pop word from stack │ + │ 0x24 │ PUSH │ Push word to stack │ + │ 0x25 │ RET │ Return from subroutine │ + │ 0x26 │ ROL │ Rotate left │ + │ 0x27 │ ROR │ Rotate right │ + │ 0x28 │ SL │ Shift left │ + │ 0x29 │ SR │ Shift right │ + │ 0x2a │ ST │ Store register to memory│ + └──────┴─────────────┴─────────────────────────┘ + + CLf - Clear flag + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + ┌──────┬─────────────┬─────────────────────────┐ + │ CODE │ NAME(S) │ DESCRIPTION │ + ├──────┼─────────────┼─────────────────────────┤ + │ 0x2b │ CLO │ Clear OF in FL Register │ + │ 0x2c │ CLC │ Clear CF in FL Register │ + │ 0x2d │ CLZ │ Clear ZF in FL Register │ + │ 0x2e │ CLN │ Clear NF in FL Register │ + │ 0x2f │ CLI │ Clear IE in FL Register │ + │ 0x30 │ CL? │ Reserved │ + │ 0x31 │ CL? │ Reserved │ + │ 0x32 │ CL? │ Reserved │ + │ 0x33 │ CL? │ Reserved │ + │ 0x34 │ CL? │ Reserved │ + │ 0x35 │ CL? │ Reserved │ + │ 0x36 │ CL? │ Reserved │ + │ 0x37 │ CL? │ Reserved │ + │ 0x38 │ CL? │ Reserved │ + │ 0x39 │ CL? │ Reserved │ + │ 0x3a │ CL? │ Reserved │ + └──────┴─────────────┴─────────────────────────┘ + + STf - Set flag + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + ┌──────┬─────────────┬─────────────────────────┐ + │ CODE │ NAME(S) │ DESCRIPTION │ + ├──────┼─────────────┼─────────────────────────┤ + │ 0x3b │ STO │ Set OF in FL Register │ + │ 0x3c │ STC │ Set CF in FL Register │ + │ 0x3d │ STZ │ Set ZF in FL Register │ + │ 0x3e │ STN │ Set NF in FL Register │ + │ 0x3f │ STI │ Set IE in FL Register │ + │ 0x40 │ ST? │ Reserved │ + │ 0x41 │ ST? │ Reserved │ + │ 0x42 │ ST? │ Reserved │ + │ 0x43 │ ST? │ Reserved │ + │ 0x44 │ ST? │ Reserved │ + │ 0x45 │ ST? │ Reserved │ + │ 0x46 │ ST? │ Reserved │ + │ 0x47 │ ST? │ Reserved │ + │ 0x48 │ ST? │ Reserved │ + │ 0x49 │ ST? │ Reserved │ + │ 0x4a │ ST? │ Reserved │ + └──────┴─────────────┴─────────────────────────┘ + + 0x4b..0x4d + ‾‾‾‾‾‾‾‾‾‾ + ┌──────┬─────────────┬─────────────────────────┐ + │ CODE │ NAME(S) │ DESCRIPTION │ + ├──────┼─────────────┼─────────────────────────┤ + │ 0x4b │ SUB │ Subtraction │ + │ 0x4c │ TEST │ Logical compare (AND) │ + │ 0x4d │ XOR │ Exclusive OR │ + └──────┴─────────────┴─────────────────────────┘ + +2. INSTRUCTION SPECIFICATIONS +──────────────────────────────────────────────────────────────────────────────── + + 0x00 ADC + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Adds the value of ACL with the first operand and the carry flag and stores + the result in ACL. SF is modified to indicate if the result is + signed (SF = 1) or unsigned (SF = 0). Sets CF on carry for unsigned math, + OF on overflow for signed math and NF flag to indicate the sign of the + signed result. Sets ZF if the result is 0 (ACL = 0 && CF = 0 && OF = 0). + + The first operand can be immediate, register immediate, direct, + register direct, indirect or register indirect. + + Operation: + + ACL := ACL + Operand1 + CF; + + 0x01 ADD + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Adds the value of ACL with the first operand and stores the result in ACL. + Sets the NF flag to indicate the sign of the signed result. + Sets CF on carry for unsigned math, OF on overflow for signed math and the + NF flag to indicate the sign of the signed result. Sets ZF if the result + is 0 (ACL = 0 && CF = 0 && OF = 0). + + The first operand can be immediate, register immediate, direct, + register direct, indirect or register indirect. + + Operation: + + ACL := ACL + Operand1; + + Carry and Overflow example: + + 0111b + 0001b = 0_1000b ; Signed int overflow, OF = 1 CF = 0 + 0111b + 1001b = 1_0000b ; Unsigned int overflow, OF = 0 CF = 1 + 0001b + 0001b = 0010b ; No overflow/carry, OF = 0 CF = 0 + + 0x02 AND + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Executes a logical AND with the current value of ACL and the first operand. + The result is then stored in ACL. Sets ZF if the result is 0, clears OF and + CF. + + Operation: + + ACL := ACL & Operand1; + + 0x03 BIN + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Reads n units of data from the I/O Bus starting at the address indicated by + Operand 1 and stores it to the destination indicated by Operand 2. + The number of units read is indicated by the value of AL. + + Both operand can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + for i := 1 to ACL do + io_read(Operand1 + i - 1, Operand2); + end + + 0x04 BOT + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Writes n units of data to the I/O Bus starting at the address indicated by + Operand 1 and stores it to the destination indicated by Operand 2. + The number of units written is indicated by the value of AL. + + Both operand can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + for i := 1 to ACL do + io_write(Operand1 + i - 1, Operand2); + end + + 0x05 CALL + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Pushes the current value of IP to the stack and jumps to the address located + by Operand 1. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + push(IP); + IP := Operand1; + + 0x07 CMP + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Subtracts Operand 1 from Operand 2 and sets the OF, CF and NF flags in the + same way as SUB. Discards the actual subtraction result. + + Both operands can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + tmp := Operand1 - Operand2; + SUBSetFlags; + + 0x08 DEC + ‾‾‾‾‾‾‾‾‾‾‾‾ + Decrements the register given in Operand 1 by one. + + Operation: + + register := register - 1; + + 0x09 DIV + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Divides the value of ACL by Operand 1 as an unsigned value and stores the + result in ACL. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + ACL := ACL / Operand1; + + 0x0a IDIV + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Divides the value of ACL by Operand 1 as a signed value and stores the + result in ACL. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + ACL := ACL / Operand1; + + 0x0b IMUL + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Multiplies the value of ACL by Operand 1 as a signed value and stores the + result in ACL. CF and OF are set if the most signficant bit, + including the sign bit, are carried over into AH. If the result fits into + AL, CF and OF are cleared. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + ACL := ACL * Operand 1; + + if ACL = AL then + CF := 0; + OF := 0; + else + CF := 1; + OF := 0; + end + + 0x0c IN + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Reads in one unit of data from the I/O bus at the address indicated by + Operand 1 and writes the result to the address indicated by Operand 2. + + Both operands can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + io_read(Operand1, Operand2); + + 0x0d INC + ‾‾‾‾‾‾‾‾‾‾‾‾ + Increments the target register indicated by Operand 1 by one. + + Operation: + + register := register + 1; + + 0x0e INT + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Triggers an interrupt with the id indicated by Operand1 if the IE flag is + set. If IE is clear, this instruction does nothing. + + Operation: + + if not IE then exit; + + Interrupt(Operand1); + + 0x0f IRET + ‾‾‾‾‾‾‾‾‾ + Returns from an interrupt and sets IE. IID is also set to 0. + This instruction should only be executed from within an interrupt handler. + + Operation: + + IE := 1; + IID := 0; + pop(IP); + + 0x10 JMP + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + IP := Operand1; + + 0x11 JZ/JE + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if ZF is set. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if ZF = 1 then + IP := Operand1; + end + + 0x12 JG + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if ZF is not set and NF is the + same as OF. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if ZF = 0 and (NF = OF) then + IP := Operand1; + end + + 0x13 JGE + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if NF is the same as OF. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if NF = OF then + IP := Operand1; + end + + 0x14 JL + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if NF is not the same as OF. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if NF <> OF then + IP := Operand1; + end + + 0x15 JLE + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if ZF is set or NF is not the + same as OF. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if ZF = 1 or (NF <> OF) then + IP := Operand1; + end; + + 0x16 JC + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if CF is set. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if CF = 1 then + IP := Operand1; + end + + 0x17 JS + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if NF is set. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if NF = 1 then + IP := Operand1; + end + + 0x18 JNZ/JNE + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if ZF is not set. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if ZF = 0 then + IP := Operand1; + end; + + 0x19 JNC + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if CF is not set. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if CF = 0 then + IP := Operand1; + end; + + 0x1a JNS + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Jumps to the address indicated by Operand 1 if NF is not set. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + if NF = 0 then + IP := Operand1; + end; + + 0x1b LD + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Loads the value indicated by Operand 2 into the register indicated by + Operand 1. + + Operand 2 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + register := Operand2; + + 0x1c MOV + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Sets the register indicated by Operand 2 to the value indicated by + Operand 1. + + Operand 1 can be immediate or register immediate. + + 0x1d MUL + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Multiplies (unsigned) the value of ACL by Operand 1 and stores the result in + ACL. If the result fits into ACL, CF and OF are cleared otherwise both get + set. + + Operand 2 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + 0x1e NEG + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + + Negates (Two's Complement) the value of Operand 1 and stores the result + in Operand 1. + + Operand 1 can be register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + Operand1 := 0 - Operand1; + + 0x1f NOP + ‾‾‾‾‾‾‾‾ + + Does nothing. + + 0x20 NOT + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Negates (One's Complement) the value of Operand 1 and stores the result in + Operand 1. + + Operand 1 can be direct, register direct, indirect or register indirect. + + Operation: + + Operand1 := 0 - Operand1; + + 0x21 OR + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Performs a logical OR with the value of ACL and Operand 1 and stores the + result in ACL. + + Operand 1 can be direct, register direct, indirect or register indirect. + + Operation: + + ACL := ACL or Operand1; + + 0x22 OUT + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Writes in one unit of data to the I/O bus to the address indicated by + Operand 2 from the address indicated by Operand 1. + + Both operands can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + io_write(Operand2, Operand1); + + 0x23 POP + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Pops the top value from the stack and writes it to the location indicated by + Operand 1. Increments SP by 2. + + Operand 1 can be register immediate, direct, register direct, indirect + or register indirect. + + Operation: + + Operand1 := *SP; + SP := SP + 2; + + 0x24 PUSH + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Pushes the value indicated by Operand 1 to the top of the stack. Decrements + SP by 2. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + SP := SP - 2; + *SP := Operand1; + + 0x25 RET + ‾‾‾‾‾‾‾‾ + Returns from a subroutine. + + Operation: + + pop(IP); + + 0x26 ROL + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Rotates the value indicated by Operand 1 left by the amount of times + indicated by Operand 2 and stores the result in Operand 1. + + Operand 1 can be register immediate, direct, register direct, indirect or + register indirect. + + Operand 2 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + tmp := Operand1 shl Operand2; + Operand1 := tmp or (tmp shr 16 and 0xff) + + 0x27 ROR + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Rotates the value indicated by Operand 1 right by the amount of times + indicated by Operand 2 and stores the result in Operand 1. + + Operand 1 can be register immediate, direct, register direct, indirect or + register indirect. + + Operand 2 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + tmp := (Operand1 shl 8) shr Operand2; + Operand1 := (Operand1 shr Operand2) or ((tmp and 0xff) shl 8) + + 0x28 SL + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Shifts the value indicated by Operand 1 left by the amount indicated by + Operand 2 and stores the result in Operand 1. + + Operand 1 can be register immediate, direct, register direct, indirect or + register indirect. + + Operand 2 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + Operand1 := Operand1 shl Operand2; + + 0x29 SR + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Shifts the value indicated by Operand 1 right by the amount indicated by + Operand 2 and stores the result in Operand 1. + + Operand 1 can be register immediate, direct, register direct, indirect or + register indirect. + + Operand 2 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + Operand1 := Operand1 shr Operand2; + + 0x2a ST + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Stores the value indicated by Operand 1 to the place in memory indicated by + Operand 2. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operand 2 can be direct, register direct, indirect or register indirect. + + Operation: + + Operand2 := Operand1; + + 0x2b CLO + ‾‾‾‾‾‾‾‾ + Clears the overflow flag. + + 0x2c CLC + ‾‾‾‾‾‾‾‾ + Clears the carry flag. + + 0x2d CLZ + ‾‾‾‾‾‾‾‾ + Clears the zero flag. + + 0x2e CLN + ‾‾‾‾‾‾‾‾ + Clears the negative flag. + + 0x2f CLI + ‾‾‾‾‾‾‾‾ + Clears the interrupt enable flag. + + 0x30..0x3a CL? + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + This range of instructions is currently invalid. + + 0x3b STO + ‾‾‾‾‾‾‾‾ + Sets the overflow flag. + + 0x3c STC + ‾‾‾‾‾‾‾‾ + Sets the carry flag. + + 0x3d STZ + ‾‾‾‾‾‾‾‾ + Sets the zero flag. + + 0x3e STN + ‾‾‾‾‾‾‾‾ + Sets the negative flag. + + 0x3f STI + ‾‾‾‾‾‾‾‾ + Sets the interrupt enable flag. + + 0x40..0x4a ST? + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + This range of instructions is currently invalid. + + 0x4b SUB + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Subtracts the value indacted by Operand 1 from the value of ACL and stores + the result in ACL. + Sets CF on carry for unsigned math, OF on overflow for signed math and the + NF flag to indicate the sign of the signed result. Sets ZF if the result + is 0 (ACL = 0 && CF = 0 && OF = 0). + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + 0x4c TEST + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Executes a logical AND with the value indicated by Operand 1 and the value + indicated by Operand 2. The result of the AND is discarded. Sets ZF if the + result is 0, clears OF and CF. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + ANDSetFlags(ACL & Operand1); + + 0x4d XOR + ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + Executes a XOR operation on the value of ACL with the value indicated by + Operand 1. Stores the result in ACL. + + Operand 1 can be immediate, register immediate, direct, register direct, + indirect or register indirect. + + Operation: + + ACL := ACL ^ Operand1; + +LICENSE +──────────────────────────────────────────────────────────────────────────────── + + MFD0816 INSTRUCTIONS by Marie Eckert is licensed under CC BY-SA 4.0, + see diff --git a/data/projects/mfd0816/index.sad b/data/projects/mfd0816/index.sad new file mode 100644 index 0000000..52ae216 --- /dev/null +++ b/data/projects/mfd0816/index.sad @@ -0,0 +1,21 @@ +{$start} +{$title} mfd0816 + +{$begin-section} about +{$head} about + +The MFD-0816 is a 16-bit fantasy CPU and based on the intel 8088. + + +* 16-bit address bus
+* 16-bit word
+* 8-bit I/O bus
+* 4x 16-bit general purpose register
+ +{$begin-section} links +{$sub-head} links +* [Version 1] Design
+* [Version 1] Instruction Set Reference
+* GitHub
+{$end-section} +{$end-section} diff --git a/test.css b/test.css index 4740db5..b02b382 100644 --- a/test.css +++ b/test.css @@ -4,7 +4,6 @@ html, body { - height: 100%; margin: 0; padding: 0; }