diff --git a/docs/architecture.md b/docs/architecture.md index f8354a1..2eed403 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -101,4 +101,7 @@ registers, words (16-bit) for data, and 24-bit values for addresses than the second, and 0 if it isn't - `GTP (reg pair) (reg pair)` (0x38) - Sets `A` to 65535 if the first reg pair is greater than the second, and 0 if it isn't +- `PUSHA (reg pair)` (0x39) - Pushes the given register pair to the stack +- `POPA (reg pair)` (0x3A) - Pops a register pair from the stack and stores it in the + given register pair - `HLT` (0xFF) - Stops execution diff --git a/source/assembler/assembler.d b/source/assembler/assembler.d index fb156eb..f22fd88 100644 --- a/source/assembler/assembler.d +++ b/source/assembler/assembler.d @@ -37,62 +37,64 @@ class Assembler { this() { // instructions - AddInstruction("nop", Opcode.NOP, []); - AddInstruction("set", Opcode.SET, [Param.Register, Param.Word]); - AddInstruction("xchg", Opcode.XCHG, [Param.Register, Param.Register]); - AddInstruction("wrb", Opcode.WRB, [Param.RegisterPair, Param.Register]); - AddInstruction("rdb", Opcode.RDB, [Param.RegisterPair]); - AddInstruction("wrw", Opcode.WRW, [Param.RegisterPair, Param.Register]); - AddInstruction("rdw", Opcode.RDW, [Param.RegisterPair]); - AddInstruction("add", Opcode.ADD, [Param.Register, Param.Register]); - AddInstruction("sub", Opcode.SUB, [Param.Register, Param.Register]); - AddInstruction("mul", Opcode.MUL, [Param.Register, Param.Register]); - AddInstruction("div", Opcode.DIV, [Param.Register, Param.Register]); - AddInstruction("mod", Opcode.MOD, [Param.Register, Param.Register]); - AddInstruction("inc", Opcode.INC, [Param.Register]); - AddInstruction("dec", Opcode.DEC, [Param.Register]); - AddInstruction("cmp", Opcode.CMP, [Param.Register, Param.Register]); - AddInstruction("not", Opcode.NOT, [Param.Register]); - AddInstruction("and", Opcode.AND, [Param.Register, Param.Register]); - AddInstruction("or", Opcode.OR, [Param.Register, Param.Register]); - AddInstruction("xor", Opcode.XOR, [Param.Register, Param.Register]); - AddInstruction("jnz", Opcode.JNZ, [Param.Addr]); - AddInstruction("jmp", Opcode.JMP, [Param.Addr]); - AddInstruction("out", Opcode.OUT, [Param.Register, Param.Register]); - AddInstruction("in", Opcode.IN, [Param.Register]); - AddInstruction("lda", Opcode.LDA, [Param.RegisterPair, Param.Addr]); - AddInstruction("incp", Opcode.INCP, [Param.RegisterPair]); - AddInstruction("decp", Opcode.DECP, [Param.RegisterPair]); - AddInstruction("setl", Opcode.SETL, [Param.Register]); - AddInstruction("cpl", Opcode.CPL, []); - AddInstruction("call", Opcode.CALL, [Param.Addr]); - AddInstruction("ret", Opcode.RET, []); - AddInstruction("int", Opcode.INT, [Param.Byte]); - AddInstruction("wra", Opcode.WRA, [Param.RegisterPair, Param.RegisterPair]); - AddInstruction("rda", Opcode.RDA, [Param.RegisterPair]); - AddInstruction("cpr", Opcode.CPR, [Param.Register, Param.Register]); - AddInstruction("cpp", Opcode.CPP, [Param.RegisterPair, Param.RegisterPair]); - AddInstruction("jmpb", Opcode.JMPB, [Param.Addr]); - AddInstruction("jnzb", Opcode.JNZB, [Param.Addr]); - AddInstruction("chk", Opcode.CHK, [Param.Register]); - AddInstruction("actv", Opcode.ACTV, [Param.Register]); - AddInstruction("addp", Opcode.ADDP, [Param.RegisterPair, Param.Register]); - AddInstruction("subp", Opcode.SUBP, [Param.RegisterPair, Param.Register]); - AddInstruction("diff", Opcode.DIFF, [Param.RegisterPair, Param.RegisterPair]); - AddInstruction("jz", Opcode.JZ, [Param.Addr]); - AddInstruction("jzb", Opcode.JZB, [Param.Addr]); - AddInstruction("rdbb", Opcode.RDBB, [Param.RegisterPair]); - AddInstruction("rdwb", Opcode.RDWB, [Param.RegisterPair]); - AddInstruction("rdab", Opcode.RDAB, [Param.RegisterPair]); - AddInstruction("wrbb", Opcode.WRBB, [Param.RegisterPair, Param.Register]); - AddInstruction("wrwb", Opcode.WRWB, [Param.RegisterPair, Param.Register]); - AddInstruction("wrab", Opcode.WRAB, [Param.RegisterPair, Param.RegisterPair]); - AddInstruction("lt", Opcode.LT, [Param.Register, Param.Register]); - AddInstruction("gt", Opcode.GT, [Param.Register, Param.Register]); - AddInstruction("cmpp", Opcode.CMPP, [Param.RegisterPair, Param.RegisterPair]); - AddInstruction("gtp", Opcode.GTP, [Param.RegisterPair, Param.RegisterPair]); - AddInstruction("ltp", Opcode.LTP, [Param.RegisterPair, Param.RegisterPair]); - AddInstruction("hlt", Opcode.HLT, []); + AddInstruction("nop", Opcode.NOP, []); + AddInstruction("set", Opcode.SET, [Param.Register, Param.Word]); + AddInstruction("xchg", Opcode.XCHG, [Param.Register, Param.Register]); + AddInstruction("wrb", Opcode.WRB, [Param.RegisterPair, Param.Register]); + AddInstruction("rdb", Opcode.RDB, [Param.RegisterPair]); + AddInstruction("wrw", Opcode.WRW, [Param.RegisterPair, Param.Register]); + AddInstruction("rdw", Opcode.RDW, [Param.RegisterPair]); + AddInstruction("add", Opcode.ADD, [Param.Register, Param.Register]); + AddInstruction("sub", Opcode.SUB, [Param.Register, Param.Register]); + AddInstruction("mul", Opcode.MUL, [Param.Register, Param.Register]); + AddInstruction("div", Opcode.DIV, [Param.Register, Param.Register]); + AddInstruction("mod", Opcode.MOD, [Param.Register, Param.Register]); + AddInstruction("inc", Opcode.INC, [Param.Register]); + AddInstruction("dec", Opcode.DEC, [Param.Register]); + AddInstruction("cmp", Opcode.CMP, [Param.Register, Param.Register]); + AddInstruction("not", Opcode.NOT, [Param.Register]); + AddInstruction("and", Opcode.AND, [Param.Register, Param.Register]); + AddInstruction("or", Opcode.OR, [Param.Register, Param.Register]); + AddInstruction("xor", Opcode.XOR, [Param.Register, Param.Register]); + AddInstruction("jnz", Opcode.JNZ, [Param.Addr]); + AddInstruction("jmp", Opcode.JMP, [Param.Addr]); + AddInstruction("out", Opcode.OUT, [Param.Register, Param.Register]); + AddInstruction("in", Opcode.IN, [Param.Register]); + AddInstruction("lda", Opcode.LDA, [Param.RegisterPair, Param.Addr]); + AddInstruction("incp", Opcode.INCP, [Param.RegisterPair]); + AddInstruction("decp", Opcode.DECP, [Param.RegisterPair]); + AddInstruction("setl", Opcode.SETL, [Param.Register]); + AddInstruction("cpl", Opcode.CPL, []); + AddInstruction("call", Opcode.CALL, [Param.Addr]); + AddInstruction("ret", Opcode.RET, []); + AddInstruction("int", Opcode.INT, [Param.Byte]); + AddInstruction("wra", Opcode.WRA, [Param.RegisterPair, Param.RegisterPair]); + AddInstruction("rda", Opcode.RDA, [Param.RegisterPair]); + AddInstruction("cpr", Opcode.CPR, [Param.Register, Param.Register]); + AddInstruction("cpp", Opcode.CPP, [Param.RegisterPair, Param.RegisterPair]); + AddInstruction("jmpb", Opcode.JMPB, [Param.Addr]); + AddInstruction("jnzb", Opcode.JNZB, [Param.Addr]); + AddInstruction("chk", Opcode.CHK, [Param.Register]); + AddInstruction("actv", Opcode.ACTV, [Param.Register]); + AddInstruction("addp", Opcode.ADDP, [Param.RegisterPair, Param.Register]); + AddInstruction("subp", Opcode.SUBP, [Param.RegisterPair, Param.Register]); + AddInstruction("diff", Opcode.DIFF, [Param.RegisterPair, Param.RegisterPair]); + AddInstruction("jz", Opcode.JZ, [Param.Addr]); + AddInstruction("jzb", Opcode.JZB, [Param.Addr]); + AddInstruction("rdbb", Opcode.RDBB, [Param.RegisterPair]); + AddInstruction("rdwb", Opcode.RDWB, [Param.RegisterPair]); + AddInstruction("rdab", Opcode.RDAB, [Param.RegisterPair]); + AddInstruction("wrbb", Opcode.WRBB, [Param.RegisterPair, Param.Register]); + AddInstruction("wrwb", Opcode.WRWB, [Param.RegisterPair, Param.Register]); + AddInstruction("wrab", Opcode.WRAB, [Param.RegisterPair, Param.RegisterPair]); + AddInstruction("lt", Opcode.LT, [Param.Register, Param.Register]); + AddInstruction("gt", Opcode.GT, [Param.Register, Param.Register]); + AddInstruction("cmpp", Opcode.CMPP, [Param.RegisterPair, Param.RegisterPair]); + AddInstruction("gtp", Opcode.GTP, [Param.RegisterPair, Param.RegisterPair]); + AddInstruction("ltp", Opcode.LTP, [Param.RegisterPair, Param.RegisterPair]); + AddInstruction("pusha", Opcode.PUSHA, [Param.RegisterPair]); + AddInstruction("popa", Opcode.POPA, [Param.RegisterPair]); + AddInstruction("hlt", Opcode.HLT, []); // special AddInstruction("db", Param.Byte); diff --git a/source/computer.d b/source/computer.d index cfb0444..fa45623 100644 --- a/source/computer.d +++ b/source/computer.d @@ -18,64 +18,66 @@ import yeti16.deviceBase; import yeti16.devices.disk; enum Opcode { - NOP = 0x00, - SET = 0x01, - XCHG = 0x02, - WRB = 0x03, - RDB = 0x04, - WRW = 0x05, - RDW = 0x06, - ADD = 0x07, - SUB = 0x08, - MUL = 0x09, - DIV = 0x0A, - MOD = 0x0B, - INC = 0x0C, - DEC = 0x0D, - CMP = 0x0E, - NOT = 0x0F, - AND = 0x10, - OR = 0x11, - XOR = 0x12, - JNZ = 0x13, - JMP = 0x14, - OUT = 0x15, - IN = 0x16, - LDA = 0x17, - INCP = 0x18, - DECP = 0x19, - SETL = 0x1A, - CPL = 0x1B, - CALL = 0x1C, - RET = 0x1D, - INT = 0x1E, - WRA = 0x1F, - RDA = 0x20, - CPR = 0x21, - CPP = 0x22, - JMPB = 0x23, - JNZB = 0x24, - CHK = 0x25, - ACTV = 0x26, - ADDP = 0x27, - SUBP = 0x28, - DIFF = 0x29, - PUSH = 0x2A, - POP = 0x2B, - JZ = 0x2C, - JZB = 0x2D, - RDBB = 0x2E, - RDWB = 0x2F, - RDAB = 0x30, - WRBB = 0x31, - WRWB = 0x32, - WRAB = 0x33, - LT = 0x34, - GT = 0x35, - CMPP = 0x36, - LTP = 0x37, - GTP = 0x38, - HLT = 0xFF + NOP = 0x00, + SET = 0x01, + XCHG = 0x02, + WRB = 0x03, + RDB = 0x04, + WRW = 0x05, + RDW = 0x06, + ADD = 0x07, + SUB = 0x08, + MUL = 0x09, + DIV = 0x0A, + MOD = 0x0B, + INC = 0x0C, + DEC = 0x0D, + CMP = 0x0E, + NOT = 0x0F, + AND = 0x10, + OR = 0x11, + XOR = 0x12, + JNZ = 0x13, + JMP = 0x14, + OUT = 0x15, + IN = 0x16, + LDA = 0x17, + INCP = 0x18, + DECP = 0x19, + SETL = 0x1A, + CPL = 0x1B, + CALL = 0x1C, + RET = 0x1D, + INT = 0x1E, + WRA = 0x1F, + RDA = 0x20, + CPR = 0x21, + CPP = 0x22, + JMPB = 0x23, + JNZB = 0x24, + CHK = 0x25, + ACTV = 0x26, + ADDP = 0x27, + SUBP = 0x28, + DIFF = 0x29, + PUSH = 0x2A, + POP = 0x2B, + JZ = 0x2C, + JZB = 0x2D, + RDBB = 0x2E, + RDWB = 0x2F, + RDAB = 0x30, + WRBB = 0x31, + WRWB = 0x32, + WRAB = 0x33, + LT = 0x34, + GT = 0x35, + CMPP = 0x36, + LTP = 0x37, + GTP = 0x38, + PUSHA = 0x39, + POPA = 0x3A, + HLT = 0xFF } enum Register { @@ -740,6 +742,17 @@ class Computer { a = v1 > v2? 0xFFFF : 0; break; } + case Opcode.PUSHA: { + auto val = ReadRegPair(NextByte()); + WriteAddr(sp, val); + sp += 3; + break; + } + case Opcode.POPA: { + sp -= 3; + WriteRegPair(NextByte(), ReadAddr(sp)); + break; + } case Opcode.HLT: { halted = true; break;