diff --git a/Programs/Fibonacci/16bitFibonacci.asm b/Programs/Fibonacci/16bitFibonacci.asm new file mode 100644 index 0000000..bafa884 --- /dev/null +++ b/Programs/Fibonacci/16bitFibonacci.asm @@ -0,0 +1,77 @@ +; A Fibonacci number generating program that uses two bytes to store the value. + +#Include Libraries/print.asm + +#Program +start: + ; Swap ValueB and ValueA. + ; First, store ValueA on the stack. + SETD ValueA + LDA + PSHA + INCD + LDA + PSHA + ; Now copy ValueB into AB. + SETD ValueB + LDA ; High byte + INCD + LDB ; Low byte + ; Now save it back to ValueA + SETD ValueA + STA ; High byte + INCD + STB ; Low byte. + ; Now retrieve value A from the stack and store it in ValueB. + POPB + POPA + SETD ValueB + STA + INCD + STB + ; Print ValueA. + SETD ValueA + LDA + CALL printByteHex + INCD + LDA + CALL printByteHex + CALL blankSpace + ; Now add ValueA and ValueB, and store the result in ValueA. + ; Add the low bytes of ValueA and ValueB + SETD ValueB + INCD + LDA + SETD ValueA + INCD + LDB + CCF + ADD + ; Store the result in ValueA. + STQ + ; Now add the high bytes of ValueA and ValueB. + DECD + LDB + SETD ValueB + LDA + ADD + ; If this addition overflows, we're done. + BRC end + ; Otherwise, store the result in ValueA. + SETD ValueA + STQ + ; And branch back to the beginning of the loop. + BRI start + end: + CALL lineFeed + HALT + +#Data + +ValueA: +; Low byte, high byte. +0x00 0x01 + +ValueB: +; Low byte, high byte. +0x00 0x00 diff --git a/Programs/Fibonacci/32bitFibonacci.asm b/Programs/Fibonacci/32bitFibonacci.asm new file mode 100644 index 0000000..0b21209 --- /dev/null +++ b/Programs/Fibonacci/32bitFibonacci.asm @@ -0,0 +1,132 @@ +; A Fibonacci number generating program that uses four bytes to store the value. + +#Include Libraries/print.asm + +#Program +start: + ; Swap ValueB and ValueA. + ; First, store ValueA on the stack. + SETD ValueA + LDA + PSHA + INCD + LDA + PSHA + INCD + LDA + PSHA + INCD + LDA + PSHA + ; Next, store ValueB on the stack. + SETD ValueB + LDA + PSHA + INCD + LDA + PSHA + INCD + LDA + PSHA + INCD + LDA + PSHA + ; Then pop ValueB into ValueA. + SETD ValueA + INCD INCD INCD + POPA + STA + DECD + POPA + STA + DECD + POPA + STA + DECD + POPA + STA + ; Then pop ValueA into ValueB. + SETD ValueB + INCD INCD INCD + POPA + STA + DECD + POPA + STA + DECD + POPA + STA + DECD + POPA + STA + ; Print ValueA. + SETD ValueA + INCD INCD INCD + LDA + CALL printByteHex + DECD + LDA + CALL printByteHex + DECD + LDA + CALL printByteHex + DECD + LDA + CALL printByteHex + CALL blankSpace + ; Now add ValueA and ValueB, and store the result in ValueA. + ; Add the lowest bytes of ValueA and ValueB. + SETD ValueB + LDB + SETD ValueA + LDA + ADD + ; Store it in ValueA's lowest byte. + STQ + ; Add the second lowest bytes of ValueA and ValueB. + SETD ValueB + INCD + LDB + SETD ValueA + INCD + LDA + ADD + ; Store it in ValueA's second lowest byte. + STQ + ; Add the second highest bytes of ValueA and ValueB. + SETD ValueB + INCD INCD + LDB + SETD ValueA + INCD INCD + LDA + ADD + ; Store it in ValueA's third lowest byte. + STQ + ; Add the highest bytes of ValueA and ValueB. + SETD ValueB + INCD INCD INCD + LDB + SETD ValueA + INCD INCD INCD + LDA + ADD + ; If this addition overflows, we're done. + BRC end + ; Otherwise, store the result in ValueA's highest byte. + STQ + ; And branch back to the beginning of the loop. + BRI start + end: + CALL lineFeed + HALT + +#Data + +ValueA: +; Lowest byte ... Highest byte. +0x01 0x00 0x00 0x00 + +ValueB: +; Lowest byte ... Highest byte. +0x00 0x00 0x00 0x00 diff --git a/Programs/Fibonacci/8bitFibonacci.asm b/Programs/Fibonacci/8bitFibonacci.asm new file mode 100644 index 0000000..cfb37c6 --- /dev/null +++ b/Programs/Fibonacci/8bitFibonacci.asm @@ -0,0 +1,33 @@ +; A Fibonacci number generating program that uses only one byte to store the value. + +#Include Libraries/print.asm + +#Program +start: + ; Load our initial values into A and B. + INIA 0x00 + CALL printByteDecimal + CALL blankSpace + ; Move the value into B. + PSHA + POPB + ; Load the next starting value into A. + INIA 0x01 + CALL printByteDecimal + CALL blankSpace + loop: + ADD ; Add the values together. + BRC end ; If the value overflows, we're done. + ; Copy A into B + PSHA + POPB + ; Copy Q into A + PSHQ + POPA + ; Print A. + CALL printByteDecimal + CALL blankSpace + BRI loop ; Loop again. + end: + CALL lineFeed + HALT diff --git a/Programs/Libraries/print.asm b/Programs/Libraries/print.asm index 4463010..b898ccd 100644 --- a/Programs/Libraries/print.asm +++ b/Programs/Libraries/print.asm @@ -12,8 +12,13 @@ lineFeed: OUTA 0x00 ; Output it. RET ; Return to the caller. -; Expects A to contain the number of spaces to print. blankSpace: + INIB 0x20 ; Set B to the ASCII value for space. + OUTB 0x00 ; Print it. + RET + +; Expects A to contain the number of spaces to print. +blankSpaces: INIB 0x20 ; Set B to the ASCII value for space. OUTB 0x00 ; Print it. BRA printDone ; If A is zero, we're done. @@ -21,13 +26,13 @@ blankSpace: BRI blankSpace ; Branch back to the loop again. printString: ; Expects Data Pointer to be set to the beginning of the string to be printed. - LDA ; Move the first character of the string into A. - BRA printDone ; If A is NULL, the string is finished, so return. - OUTA 0x00 ; Output the character. - INCD ; Increment Data Pointer to the next character. - BRI printString ; Branch to the beginning of the loop. - printDone: - RET ; Return to the caller. + LDA ; Move the first character of the string into A. + BRA printDone ; If A is NULL, the string is finished, so return. + OUTA 0x00 ; Output the character. + INCD ; Increment Data Pointer to the next character. + BRI printString ; Branch to the beginning of the loop. + printDone: + RET ; Return to the caller. ; Expects A to contain the value to be printed in decimal form. printByteDecimal: diff --git a/Source/Assembler/assembly.c b/Source/Assembler/assembly.c index 22e0441..8447712 100644 --- a/Source/Assembler/assembly.c +++ b/Source/Assembler/assembly.c @@ -17,13 +17,11 @@ Instruction instruction_set[] = { {0x01, "SUB"}, {0x02, "AND"}, {0x03, "OR"}, - {0x04, "NOR"}, - {0x05, "NAND"}, - {0x06, "XOR"}, - {0x07, "NOTA"}, - {0x08, "NOTB"}, - {0x09, "SHL"}, - {0x0A, "SHR"}, + {0x04, "XOR"}, + {0x05, "NOTA"}, + {0x06, "NOTB"}, + {0x07, "SHL"}, + {0x08, "SHR"}, // Branch Operations: {0x10, "BRI"}, {0x11, "BRQ"}, @@ -31,10 +29,6 @@ Instruction instruction_set[] = { {0x13, "BRB"}, {0x14, "BRC"}, {0x17, "CALL"}, - {0x18, "CALLA"}, - {0x19, "CALLB"}, - {0x1A, "CALLQ"}, - {0x1B, "CALLCF"}, {0x1F, "RET"}, // Register Operations: {0x20, "RSTA"}, @@ -65,6 +59,8 @@ Instruction instruction_set[] = { {0x45, "STA"}, {0x46, "STB"}, {0x47, "SETD"}, + {0x48, "DPUP"}, + {0x49, "DPDN"}, // Output Operations: {0xD0, "OUTQ"}, {0xD1, "OUTA"}, diff --git a/Source/Emulator/cpu.c b/Source/Emulator/cpu.c index ec1b919..6dbe6be 100644 --- a/Source/Emulator/cpu.c +++ b/Source/Emulator/cpu.c @@ -33,27 +33,27 @@ void genericBranch(CPURegisters *cpu){ void genericCall(CPURegisters *cpu){ // Order, low byte, high byte - cpu->Data[cpu->StackPointer] = cpu->ProgramCounter & 0xFF; - cpu->StackPointer--; - cpu->Data[cpu->StackPointer] = (cpu->ProgramCounter >> 8) & 0xFF; - cpu->StackPointer--; - // Push the Data Pointer to the Stack. - // Order, low byte, high byte - cpu->Data[cpu->StackPointer] = cpu->DataPointer & 0xFF; - cpu->StackPointer--; - cpu->Data[cpu->StackPointer] = (cpu->DataPointer >> 8) & 0xFF; - cpu->StackPointer--; - // Push Q to the Stack. - cpu->Data[cpu->StackPointer] = cpu->Q; - cpu->StackPointer--; - // Push B to the Stack. - cpu->Data[cpu->StackPointer] = cpu->B; - cpu->StackPointer--; - // Push A to the Stack. - cpu->Data[cpu->StackPointer] = cpu->A; - cpu->StackPointer--; - // Perform a Generic Branch to the Address. - genericBranch(cpu); + cpu->Data[cpu->StackPointer] = cpu->ProgramCounter & 0xFF; + cpu->StackPointer--; + cpu->Data[cpu->StackPointer] = (cpu->ProgramCounter >> 8) & 0xFF; + cpu->StackPointer--; + // Push the Data Pointer to the Stack. + // Order, low byte, high byte + cpu->Data[cpu->StackPointer] = cpu->DataPointer & 0xFF; + cpu->StackPointer--; + cpu->Data[cpu->StackPointer] = (cpu->DataPointer >> 8) & 0xFF; + cpu->StackPointer--; + // Push Q to the Stack. + cpu->Data[cpu->StackPointer] = cpu->Q; + cpu->StackPointer--; + // Push B to the Stack. + cpu->Data[cpu->StackPointer] = cpu->B; + cpu->StackPointer--; + // Push A to the Stack. + cpu->Data[cpu->StackPointer] = cpu->A; + cpu->StackPointer--; + // Perform a Generic Branch to the Address. + genericBranch(cpu); } uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) { @@ -88,33 +88,25 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) { cpu->Q = cpu->A|cpu->B; break; case 0x04: - // NAND - A nand B -> Q - cpu->Q = ~(cpu->A&cpu->B); - break; - case 0x05: - // NOR - A nor B -> Q - cpu->Q = ~(cpu->A|cpu->B); - break; - case 0x06: // XOR - A xor B -> Q cpu->Q = cpu->A^cpu->B; break; - case 0x07: + case 0x05: // NOTA - not A -> Q cpu->Q = ~cpu->A; break; - case 0x08: + case 0x06: // NOTB - not B -> Q cpu->Q = ~cpu->B; break; - case 0x09: + case 0x07: // SHL - Shift AB left. shiftRegister = ((uint16_t)cpu->A << 8) | cpu->B; shiftRegister = (shiftRegister << 1) | (shiftRegister >> 15); cpu->A = shiftRegister >> 8; cpu->B = shiftRegister & 0xFF; break; - case 0x0A: + case 0x08: // SHR - Shift AB right. shiftRegister = ((uint16_t)cpu->A << 8) | cpu->B; shiftRegister = (shiftRegister >> 1) | (shiftRegister << 15); @@ -167,29 +159,29 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) { // CALL - Push the Program Counter to the Stack, and perform an immediate branch. genericCall(cpu); break; - case 0x18: - // CALLA - if (cpu->A == 0) { - genericCall(cpu); - } - break; - case 0x19: - // CALLB - if (cpu->B == 0) { - genericCall(cpu); - } - break; - case 0x1A: - // CALLQ - if (cpu->Q == 0) { - genericCall(cpu); - } - case 0x1B: - // CALLCF - if (cpu->Status & 0x01) { - genericCall(cpu); - } - break; + // case 0x18: + // // CALLA + // if (cpu->A == 0) { + // genericCall(cpu); + // } + // break; + // case 0x19: + // // CALLB + // if (cpu->B == 0) { + // genericCall(cpu); + // } + // break; + // case 0x1A: + // // CALLQ + // if (cpu->Q == 0) { + // genericCall(cpu); + // } + // case 0x1B: + // // CALLCF + // if (cpu->Status & 0x01) { + // genericCall(cpu); + // } + // break; case 0x1F: // RET - Return from subroutine, restore the registers and set the Program Counter to the Return Address. // Pop A from the Stack. @@ -213,6 +205,7 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) { cpu->ProgramCounter = cpu->ProgramCounter | (uint16_t)cpu->Data[cpu->StackPointer]; // Add 2 to the Program Counter to skip over the address when it returns. cpu->ProgramCounter += 2; + break; // // 2x - Register Operations: @@ -347,6 +340,16 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) { Address |= (uint16_t)cpu->Program[cpu->ProgramCounter]; cpu-> DataPointer = Address; break; + case 0x48: + // DPUP - Offset the Data Pointer up by the value of the next byte of Program Memory. + cpu->ProgramCounter++; + cpu->DataPointer += cpu->Program[cpu->ProgramCounter]; + break; + case 0x49: + // DPDN - Offset the Data Pointer down by the value of the next byte of Program Memory. + cpu->ProgramCounter++; + cpu->DataPointer -= cpu->Program[cpu->ProgramCounter]; + break; // // Dx - Output Operations: // diff --git a/SplitBit Programming Manual.md b/SplitBit Programming Manual.md index 2886fc0..510f7fe 100644 --- a/SplitBit Programming Manual.md +++ b/SplitBit Programming Manual.md @@ -16,22 +16,20 @@ It has six registers: ## List of Instructions: -### Arithmetic and Logic Operations: 11 Instructions +### Arithmetic and Logic Operations: 9 Instructions Hex Code | Mnemonic | Description -- | -- | -- 00 | ADD | Adds A, B, and the Carry Flag, the result is stored in Q. 01 | SUB | Subtracts B and the Carry Flag from A, the result is stored in Q. 02 | AND | Bitwise and of A and B, the result is stored in Q. 03 | OR | Bitwise or of A and B, the result is stored in Q. -04 | NOR | Bitwise nor of A and B, the result is stored in Q. -05 | NAND | Bitwise nand of A and B, the result is stored in Q. -06 | XOR | Bitwise xor of A and B, the result is stored in Q. -07 | NOTA | Bitwise inversion of A, the result is stored in Q. -08 | NOTB | Bitwise inversion of B, the result is stored in Q. -09 | SHL | A and B form a circular shift register. Rotate this register left. -0A | SHR | A and B form a circular shift register. Rotate this register right. +04 | XOR | Bitwise xor of A and B, the result is stored in Q. +05 | NOTA | Bitwise inversion of A, the result is stored in Q. +06 | NOTB | Bitwise inversion of B, the result is stored in Q. +07 | SHL | A and B form a circular shift register. Rotate this register left. +08 | SHR | A and B form a circular shift register. Rotate this register right. -### Branch Operations: 11 Instructions +### Branch and Subroutine Operations: 7 Instructions Hex Code | Mnemonic | Description -- | -- | -- 10 | BRI | Branch Immediately. Loads the immediate next two bytes of Program Memory into the Program Counter, first the most significant byte, then the least. @@ -40,10 +38,6 @@ Hex Code | Mnemonic | Description 13 | BRB | Branch on B. If B is zero, loads the immediate next two bytes of Program Memory into the Program Counter. 14 | BRC | Branch if Carry is set. 17 | CALL | Call subroutine. Stores all the registers to the Stack, A, B, Q, the Data Pointer, and the Program Counter, then performs an immediate branch. -18 | CALLA | Conditional Call on A. Calls subroutine if A is zero. -19 | CALLB | Conditional Call on B. Calls subroutine if B is zero. -1A | CALLQ | Conditional Call on Q. Calls subroutine if Q is zero. -1B | CALLCF | Conditional Call on Carry. Calls subroutine if the Carry Flag is set. 1F | RET | Restores all registers from the Stack, then immediately branches to the Return Address by setting the Program Counter to the next instruction after the last CALL. @@ -73,17 +67,19 @@ Hex Code | Mnemonic | Description 35 | POPB | Reads the location referenced by the Stack Pointer from Data Memory into B then increments the Stack Pointer. 36 | POPD | Restores the Program Counter from the top two bytes in the stack, increments the Stack Pointer by two. -### Data Operations: 8 Instructions +### Data Operations: 10 Instructions Hex Code | Mnemonic | Description -- | -- | -- 40 | INCD | Increments the Data Pointer. 41 | DECD | Decrements the Data Pointer. 42 | LDA | Loads the byte referenced from Data Memory by the Data Pointer into A. 43 | LDB | Loads the byte referenced from Data Memory by the Data Pointer into B. -44 | STQ | Stores Q into the byte referenced by the Data Pointer in Data Mmoery. +44 | STQ | Stores Q into the byte referenced by the Data Pointer in Data Memory. 45 | STA | Stores A into the byte referenced by the Data Pointer in Data Memory. 46 | STB | Stores B into the byte referenced by the Data Pointer in Data Memory. 47 | SETD | Loads the next two bytes of Program Memory into the Data Pointer. +48 | DPUP | Offset Data Pointer up by the value of the immediate next byte of Program Memory. +49 | DPDN | Offset Data Pointer down by the value of the immediate next byte of Program Memory. ### Output Operations: 3 Instructions