Added new instructions.
Added CCF - Clear Carry Flag Added BRC - Branch on Carry Flag Improved CALL and RET - All registers but status now saved and restored.
This commit is contained in:
+80
-41
@@ -5,55 +5,94 @@
|
|||||||
; 10/27/2024
|
; 10/27/2024
|
||||||
|
|
||||||
#Program
|
#Program
|
||||||
BRI Start ; Branch immediately to the start of the program.
|
BRI start ; Branch immediately to the start of the program.
|
||||||
|
|
||||||
printString:
|
|
||||||
CALL saveRegisters ; Store the registers so we can restore them later.
|
|
||||||
printLoop:
|
|
||||||
LDA ; Move the first character of the string into A.
|
|
||||||
BRA Return ; If A is NULL, the string is finished, so return.
|
|
||||||
OUTA 0x00 ; Output the character.
|
|
||||||
INCD ; Increment Data Pointer to the next character.
|
|
||||||
BRI printLoop ; Branch to the beginning of the loop.
|
|
||||||
|
|
||||||
lineFeed:
|
lineFeed:
|
||||||
CALL saveRegisters ; Save the registers so they can be restored.
|
|
||||||
INIA 0x0A ; Load the character for linefeed into A.
|
INIA 0x0A ; Load the character for linefeed into A.
|
||||||
OUTA 0x00 ; Output it.
|
OUTA 0x00 ; Output it.
|
||||||
CALL restoreRegisters
|
|
||||||
BRI Return ; We're done.
|
|
||||||
|
|
||||||
saveRegisters: ; Subroutine for storing the registers.
|
|
||||||
PSHD ; Store the Data Pointer, push it to the stack.
|
|
||||||
SETD Registers ; Set the Data Pointer to the address for the registers.
|
|
||||||
STQ ; Store Q.
|
|
||||||
INCD ; Move to the next address.
|
|
||||||
STA ; Store A.
|
|
||||||
INCD ; Move to the next address.
|
|
||||||
STB ; Store B.
|
|
||||||
POPD ; Restore the Data Pointer.
|
|
||||||
RET ; Return to the caller.
|
RET ; Return to the caller.
|
||||||
|
|
||||||
restoreRegisters:
|
printString: ; Expects Data Pointer to be set to the beginning of the string to be printed.
|
||||||
PSHD ; Save the Data Pointer.
|
LDA ; Move the first character of the string into A.
|
||||||
SETD Registers ; Set the Data Pointer to the registers address.
|
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 Data Pointer to be set to the one byte integer value to be printed in decimal form.
|
||||||
|
printDecimal:
|
||||||
|
LDA ; Load the value into A.
|
||||||
|
PSHA ; Save it onto the stack.
|
||||||
|
; Clear the buffer we're going to write into.
|
||||||
|
SETD DecimalValue ; Set the Data Pointer to the buffer.
|
||||||
RSTB ; Set B to 0.
|
RSTB ; Set B to 0.
|
||||||
LDA ; Load the value for Q into A.
|
STB ; Store it in the buffer.
|
||||||
ADD ; Add 0 to move the value to Q.
|
INCD ; Increment to the tens place.
|
||||||
INCD ; Move to the next register value.
|
STB ; Store 0 in it.
|
||||||
LDA ; Load A with its value.
|
INCD ; Increment to the hundred's place.
|
||||||
INCD ; Move to the next register value.
|
STB ; Store 0 in it.
|
||||||
LDB ; Load B with its value.
|
INIB 0d10 ; Load 10 into B.
|
||||||
POPD ; Restore the Data Pointer.
|
printDecimalLoopStart:
|
||||||
RET ; Return to the caller.
|
POPA ; Pop the value to A from the stack.
|
||||||
|
CCF ; Clear the Carry Flag.
|
||||||
|
SUB ; Subtract 10 from the value in A.
|
||||||
|
BRC getOnes ; If 10 is bigger than A, We're done looping and A contains the ones.
|
||||||
|
BRA getOnes ; If the value 0, we're also done.
|
||||||
|
; Otherwise, increment the tens place.
|
||||||
|
SETD DecimalValue ; Set the Data Pointer to the buffer.
|
||||||
|
INCD ; Increment to the tens place.
|
||||||
|
PSHQ ; Save the new value onto the stack.
|
||||||
|
LDA ; Load the number of tens into A.
|
||||||
|
INCA ; Increment it.
|
||||||
|
; Now check to see if there are ten tens and we need to carry to the hundreds.
|
||||||
|
CCF ; Clear the Carry Flag.
|
||||||
|
SUB ; Subtract 10 from A.
|
||||||
|
BRQ incrementHundreds ; If Q is 0, set the tens to 0 and increment the hundreds place.
|
||||||
|
STA ; Otherwise, store the value back to the tens place.
|
||||||
|
BRI printDecimalLoopStart ; and loop again.
|
||||||
|
incrementHundreds:
|
||||||
|
STQ ; Store 0 in the tens place.
|
||||||
|
INCD ; Increment the Data Pointer to the hundreds place.
|
||||||
|
LDA ; Load it into A.
|
||||||
|
INCA ; Increment it.
|
||||||
|
STA ; Store it back again.
|
||||||
|
BRI printDecimalLoopStart ; and Loop again.
|
||||||
|
getOnes:
|
||||||
|
SETD DecimalValue ; Set the Data Pointer to the ones place.
|
||||||
|
STA ; Store A in it.
|
||||||
|
; At this point we're done. We just need to print the digits with the printDecimalDigit subroutine.
|
||||||
|
INCD INCD ; Increment the Data Pointer twice to the hundreds place.
|
||||||
|
decimalCheckLoop:
|
||||||
|
LDA ; Load the value into A.
|
||||||
|
BRA checkTens ; If the hundreds are 0, skip printing their digit.
|
||||||
|
CALL printDecimalDigit ; Otherwise, print it.
|
||||||
|
DECD
|
||||||
|
CALL printDecimalDigit ; And the tens place, too.
|
||||||
|
BRI printOnes ; And finally, the ones.
|
||||||
|
checkTens:
|
||||||
|
DECD ; Decrement to the tens place.
|
||||||
|
LDA ; Load it into A.
|
||||||
|
BRA printOnes ; If the tens are zero, skip printing their digit, too.
|
||||||
|
CALL printDecimalDigit ; Otherwise, print it.
|
||||||
|
printOnes:
|
||||||
|
DECD ; Decrement to the ones place.
|
||||||
|
CALL printDecimalDigit ; Print it no matter what.
|
||||||
|
RET ; We're done, return to the caller.
|
||||||
|
|
||||||
Return:
|
printDecimalDigit: ; Expects Data Pointer to be set to the value to print.
|
||||||
CALL restoreRegisters ; Restore the registers.
|
LDA ; Load the value into A.
|
||||||
RET ; Return to the caller.
|
INIB 0x30 ; Load ASCII offset for numbers into B.
|
||||||
|
CCF ; Clear the Carry Flag.
|
||||||
|
ADD ; Add it to A.
|
||||||
|
OUTQ 0x00 ; Send it to the output.
|
||||||
|
RET ; Return from subroutine.
|
||||||
|
|
||||||
#Data
|
#Data
|
||||||
|
|
||||||
Registers: ; This is where saveRegisters stores the registers temporarily.
|
; This is where printDecimal stores its result.
|
||||||
0x00 ; Q Register
|
DecimalValue:
|
||||||
0x00 ; A Register
|
0x00 ; The ones place.
|
||||||
0x00 ; B Register
|
0x00 ; The tens place.
|
||||||
|
0x00 ; The hundreds place.
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
; Tests for the printDecimal subroutine.
|
||||||
|
|
||||||
|
#Include print.asm
|
||||||
|
|
||||||
|
#Program
|
||||||
|
|
||||||
|
start:
|
||||||
|
INIB 0xFF ; Load 255 into B.
|
||||||
|
loop:
|
||||||
|
SETD MyDecimal ; Set D to our decimal.
|
||||||
|
SUB
|
||||||
|
CCF ; Clear the Carry Flag.
|
||||||
|
CALL printDecimal ; Print the value.
|
||||||
|
LDA ; Load the value into A.
|
||||||
|
INCA ; Increment it.
|
||||||
|
STA ; Store it again.
|
||||||
|
SETD Space
|
||||||
|
CALL printString ; Print a space between the the numbers.
|
||||||
|
BRQ end ; If Q is zero, we're done.
|
||||||
|
BRI loop ; Branch back to the start of the loop.
|
||||||
|
end:
|
||||||
|
CALL lineFeed
|
||||||
|
HALT
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
MyDecimal:
|
||||||
|
0x00
|
||||||
|
|
||||||
|
Space:
|
||||||
|
" "
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#Include print.asm
|
||||||
|
|
||||||
|
#Program
|
||||||
|
|
||||||
|
start:
|
||||||
|
INIB 0d10
|
||||||
|
SETD byte
|
||||||
|
loop:
|
||||||
|
CALL printDecimalDigit
|
||||||
|
LDA
|
||||||
|
INCA
|
||||||
|
STA
|
||||||
|
SUB
|
||||||
|
BRQ end
|
||||||
|
CALL lineFeed
|
||||||
|
BRI loop
|
||||||
|
end:
|
||||||
|
CALL lineFeed
|
||||||
|
HALT
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
byte:
|
||||||
|
0x00
|
||||||
+19
-7
@@ -8,13 +8,25 @@
|
|||||||
#Include print.asm
|
#Include print.asm
|
||||||
|
|
||||||
#Program
|
#Program
|
||||||
Start:
|
|
||||||
SETD myString ; Set the Data Pointer to the string we want to print.
|
start:
|
||||||
CALL printString ; Call the subroutine.
|
SETD MyString ; Set the Data Pointer to the start of MyString.
|
||||||
CALL lineFeed ; Call the linefeed subroutine.
|
CALL printString ; Call the string printing subroutine.
|
||||||
HALT ; Stop the CPU.
|
CALL lineFeed ; Call the line feed subroutine to end the line.
|
||||||
|
SETD MyDecimal ; Set the Data Pointer to the value to print as a decimal.
|
||||||
|
CALL printDecimal ; Call the decimal printing subroutine.
|
||||||
|
SETD MyMessage ; Set the Data Pointer to another string.
|
||||||
|
CALL printString ; Call the string printing subroutine again.
|
||||||
|
CALL lineFeed ; Call the line feed subroutine to end the line.
|
||||||
|
HALT ; Stop the program.
|
||||||
|
|
||||||
#Data
|
#Data
|
||||||
|
|
||||||
myString:
|
MyString:
|
||||||
"Hello, World!"
|
"Hello, World! "
|
||||||
|
|
||||||
|
MyDecimal:
|
||||||
|
0d42
|
||||||
|
|
||||||
|
MyMessage:
|
||||||
|
" is the great answer."
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ Instruction instruction_set[] = {
|
|||||||
{0x13, "BRB"},
|
{0x13, "BRB"},
|
||||||
{0x14, "CALL"},
|
{0x14, "CALL"},
|
||||||
{0x15, "RET"},
|
{0x15, "RET"},
|
||||||
|
{0x16, "BRC"},
|
||||||
// Register Operations:
|
// Register Operations:
|
||||||
{0x20, "RSTA"},
|
{0x20, "RSTA"},
|
||||||
{0x21, "RSTB"},
|
{0x21, "RSTB"},
|
||||||
@@ -40,6 +41,7 @@ Instruction instruction_set[] = {
|
|||||||
{0x27, "LDB"},
|
{0x27, "LDB"},
|
||||||
{0x28, "INIA"},
|
{0x28, "INIA"},
|
||||||
{0x29, "INIB"},
|
{0x29, "INIB"},
|
||||||
|
{0x2F, "CCF"},
|
||||||
// Stack Operations:
|
// Stack Operations:
|
||||||
{0x30, "PSHQ"},
|
{0x30, "PSHQ"},
|
||||||
{0x31, "PSHA"},
|
{0x31, "PSHA"},
|
||||||
|
|||||||
+50
-8
@@ -121,16 +121,55 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) {
|
|||||||
cpu->StackPointer--;
|
cpu->StackPointer--;
|
||||||
cpu->Data[cpu->StackPointer] = (cpu->ProgramCounter >> 8) & 0xFF;
|
cpu->Data[cpu->StackPointer] = (cpu->ProgramCounter >> 8) & 0xFF;
|
||||||
cpu->StackPointer--;
|
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);
|
genericBranch(cpu);
|
||||||
break;
|
break;
|
||||||
case 0x15:
|
case 0x15:
|
||||||
// RET - Return from subroutine, restore the Program Counter from the Stack.
|
// RET - Return from subroutine, restore the registers and set the Program Counter to the Return Address.
|
||||||
// POPP - Pop Data to the Program Counter
|
// Pop A from the Stack.
|
||||||
|
cpu->StackPointer++;
|
||||||
|
cpu->A = cpu->Data[cpu->StackPointer];
|
||||||
|
// Pop B from the Stack.
|
||||||
|
cpu->StackPointer++;
|
||||||
|
cpu->B = cpu->Data[cpu->StackPointer];
|
||||||
|
// Pop Q from the Stack.
|
||||||
|
cpu->StackPointer++;
|
||||||
|
cpu->Q = cpu->Data[cpu->StackPointer];
|
||||||
|
// Pop the Data Pointer from the Stack.
|
||||||
|
cpu->StackPointer++;
|
||||||
|
cpu->DataPointer = (uint16_t)cpu->Data[cpu->StackPointer] << 8;
|
||||||
|
cpu->StackPointer++;
|
||||||
|
cpu->DataPointer |= (uint16_t)cpu->Data[cpu->StackPointer];
|
||||||
|
// Pop the Return Address from the Stack.
|
||||||
cpu->StackPointer++;
|
cpu->StackPointer++;
|
||||||
cpu->ProgramCounter = (uint16_t)cpu->Data[cpu->StackPointer] << 8;
|
cpu->ProgramCounter = (uint16_t)cpu->Data[cpu->StackPointer] << 8;
|
||||||
cpu->StackPointer++;
|
cpu->StackPointer++;
|
||||||
cpu->ProgramCounter = cpu->ProgramCounter | (uint16_t)cpu->Data[cpu->StackPointer];
|
cpu->ProgramCounter = cpu->ProgramCounter | (uint16_t)cpu->Data[cpu->StackPointer];
|
||||||
cpu->ProgramCounter += 2; // Because it needs to skip over the address when it returns.
|
// Add 2 to the Program Counter to skip over the address when it returns.
|
||||||
|
cpu->ProgramCounter += 2;
|
||||||
|
break;
|
||||||
|
case 0x16:
|
||||||
|
// BRC - Do an immediate branch is the Carry Flag is set.
|
||||||
|
if (cpu->Status & 0x01) {
|
||||||
|
genericBranch(cpu);
|
||||||
|
} else {
|
||||||
|
cpu->ProgramCounter+=2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
// 2x - Register Operations:
|
// 2x - Register Operations:
|
||||||
@@ -177,6 +216,10 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) {
|
|||||||
cpu->ProgramCounter++;
|
cpu->ProgramCounter++;
|
||||||
cpu->B = cpu->Program[cpu->ProgramCounter];
|
cpu->B = cpu->Program[cpu->ProgramCounter];
|
||||||
break;
|
break;
|
||||||
|
case 0x2F:
|
||||||
|
// CCF - Clear the Carry Flag.
|
||||||
|
cpu->Status &= ~0x01;
|
||||||
|
break;
|
||||||
//
|
//
|
||||||
// 3x - Stack Operations:
|
// 3x - Stack Operations:
|
||||||
//
|
//
|
||||||
@@ -195,9 +238,8 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) {
|
|||||||
cpu->Data[cpu->StackPointer] = cpu->B;
|
cpu->Data[cpu->StackPointer] = cpu->B;
|
||||||
cpu->StackPointer--;
|
cpu->StackPointer--;
|
||||||
break;
|
break;
|
||||||
break;
|
|
||||||
case 0x33:
|
case 0x33:
|
||||||
// PSHD - Push the Data Pointer to the Stack.
|
// PSHD - Push the Data Pointer Address to the Stack.
|
||||||
// Order, low byte, high byte
|
// Order, low byte, high byte
|
||||||
cpu->Data[cpu->StackPointer] = cpu->DataPointer & 0xFF;
|
cpu->Data[cpu->StackPointer] = cpu->DataPointer & 0xFF;
|
||||||
cpu->StackPointer--;
|
cpu->StackPointer--;
|
||||||
@@ -205,18 +247,18 @@ uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) {
|
|||||||
cpu->StackPointer--;
|
cpu->StackPointer--;
|
||||||
break;
|
break;
|
||||||
case 0x34:
|
case 0x34:
|
||||||
// POPA - Pop Data to A.
|
// POPA - Pop A from the Stack.
|
||||||
cpu->StackPointer++;
|
cpu->StackPointer++;
|
||||||
cpu->A = cpu->Data[cpu->StackPointer];
|
cpu->A = cpu->Data[cpu->StackPointer];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 0x35:
|
case 0x35:
|
||||||
// POPB - Pop Data to B.
|
// POPB - Pop B from the Stack.
|
||||||
cpu->StackPointer++;
|
cpu->StackPointer++;
|
||||||
cpu->B = cpu->Data[cpu->StackPointer];
|
cpu->B = cpu->Data[cpu->StackPointer];
|
||||||
break;
|
break;
|
||||||
case 0x36:
|
case 0x36:
|
||||||
// POPD - Pop Data to the Data Pointer
|
// POPD - Pop Data Address from the Stack.
|
||||||
cpu->StackPointer++;
|
cpu->StackPointer++;
|
||||||
cpu->DataPointer = (uint16_t)cpu->Data[cpu->StackPointer] << 8;
|
cpu->DataPointer = (uint16_t)cpu->Data[cpu->StackPointer] << 8;
|
||||||
cpu->StackPointer++;
|
cpu->StackPointer++;
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ The assembler will accept:
|
|||||||
Labels may be a string of up to 32 alphanumeric characters that must end with a semicolon, ':'.
|
Labels may be a string of up to 32 alphanumeric characters that must end with a semicolon, ':'.
|
||||||
|
|
||||||
```
|
```
|
||||||
ProgramStart:
|
programStart:
|
||||||
|
|
||||||
LoopStart:
|
loopStart:
|
||||||
|
|
||||||
ErrorHandler01:
|
errorHandler01:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -36,25 +36,28 @@ SplitBit programs may have a Data Segment. You may define the start of the data
|
|||||||
## An Example SplitBit Assembly Program:
|
## An Example SplitBit Assembly Program:
|
||||||
|
|
||||||
```
|
```
|
||||||
; This is a basic hello world program for the SplitBit CPU.
|
; This is a slightly more advanced hello world program that demonstrates some SplitBit programming conventions.
|
||||||
; We'll create a loop that outputs each byte of our string to Output 0, the text console.
|
|
||||||
|
|
||||||
#Program
|
#Program
|
||||||
|
|
||||||
Start:
|
start: ; By uninforced convention, Program Labels start with a lowercase letter.
|
||||||
LDA ; Load a byte of the string into A.
|
SETD HelloString ; Set the Data Pointer to the address of the string.
|
||||||
BRA End ; If A is zero, branch out of the loop.
|
CALL printString ; Call the string printing subroutine.
|
||||||
OUTA 0x00 ; Output the value in A to Port 0, the text console.
|
HALT ; End the program.
|
||||||
INCD ; Increment the Data Pointer to the next byte of the string.
|
|
||||||
BRI Start ; Branch immediately to the start of the loop.
|
|
||||||
|
|
||||||
End:
|
; This is a reusable subroutine that could be includedd in other programs.
|
||||||
INIA 0x0A ; We'll load a linefeed into A and output it to make it look nice.
|
printString: ; Expects Data Pointer to be set to the beginning of the string to be printed.
|
||||||
OUTA 0x00 ; Output it to the text console.
|
LDA ; Move the first character of the string into A.
|
||||||
HALT ; Terminate the program.
|
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.
|
||||||
|
|
||||||
#Data
|
#Data
|
||||||
|
|
||||||
|
HelloString: ; By uninforced convention, Data Labels start with a capital letter.
|
||||||
"Hello, World!"
|
"Hello, World!"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -29,17 +29,18 @@ Hex Code | Mnemonic | Description
|
|||||||
07 | NOTA | Bitwise inversion of A, 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.
|
08 | NOTB | Bitwise inversion of B, the result is stored in Q.
|
||||||
|
|
||||||
### Branch Operations: 4 Instructions
|
### Branch Operations: 7 Instructions
|
||||||
Hex Code | Mnemonic | Description
|
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.
|
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.
|
||||||
11 | BRQ | Branch on Q. If Q is zero, loads the immediate next two bytes of Program Memory into the Program Counter.
|
11 | BRQ | Branch on Q. If Q is zero, loads the immediate next two bytes of Program Memory into the Program Counter.
|
||||||
12 | BRA | Branch on A. If A is zero, loads the immediate next two bytes of Program Memory into the Program Counter.
|
12 | BRA | Branch on A. If A is zero, loads the immediate next two bytes of Program Memory into the Program Counter.
|
||||||
13 | BRB | Branch on B. If B is zero, loads the immediate next two bytes of Program Memory into the Program Counter.
|
13 | BRB | Branch on B. If B is zero, loads the immediate next two bytes of Program Memory into the Program Counter.
|
||||||
14 | CALL | Push the Program Counter to the Stack, loads the immediate next two bytes of Program Memory into the Program Counter.
|
14 | CALL | Stores all the registers to the Stack, A, B, Q, the Data Pointer, and the Program Counter, then performs an immediate branch.
|
||||||
15 | RET | Restores the Program Counter from the Stack, used to return from subroutines.
|
15 | 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.
|
||||||
|
16 | BRC | Branch if Carry is set.
|
||||||
|
|
||||||
### Register Operations: 6 Instructions
|
### Register Operations: 11 Instructions
|
||||||
| Hex Code | Mnemonic | Description |
|
| Hex Code | Mnemonic | Description |
|
||||||
| -------- | -------- | ------------------- |
|
| -------- | -------- | ------------------- |
|
||||||
| 20 | RSTA | Resets A to 0. |
|
| 20 | RSTA | Resets A to 0. |
|
||||||
@@ -52,8 +53,9 @@ Hex Code | Mnemonic | Description
|
|||||||
| 27 | LDB | Loads Data to B via the Data Pointer.
|
| 27 | LDB | Loads Data to B via the Data Pointer.
|
||||||
| 28 | INIA | Loads the next byte of Program Memory to A. |
|
| 28 | INIA | Loads the next byte of Program Memory to A. |
|
||||||
| 29 | INIB | Loads the next byte of Program Memory to B. |
|
| 29 | INIB | Loads the next byte of Program Memory to B. |
|
||||||
|
| 2F | CCF | Clears the Carry Flag. |
|
||||||
|
|
||||||
### Stack Operations: 9 Instructions
|
### Stack Operations: 7 Instructions
|
||||||
Hex Code | Mnemonic | Description
|
Hex Code | Mnemonic | Description
|
||||||
-- | -- | --
|
-- | -- | --
|
||||||
30 | PSHQ | Stores Q into Data Memory at the location referenced by the Stack Pointer then decrements the Stack Pointer.
|
30 | PSHQ | Stores Q into Data Memory at the location referenced by the Stack Pointer then decrements the Stack Pointer.
|
||||||
@@ -64,7 +66,7 @@ Hex Code | Mnemonic | Description
|
|||||||
35 | POPB | Reads the location referenced by the Stack Pointer from Data Memory into B then increments the Stack Pointer.
|
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.
|
36 | POPD | Restores the Program Counter from the top two bytes in the stack, increments the Stack Pointer by two.
|
||||||
|
|
||||||
### Data Operations: 7 Instructions
|
### Data Operations: 8 Instructions
|
||||||
Hex Code | Mnemonic | Description
|
Hex Code | Mnemonic | Description
|
||||||
-- | -- | --
|
-- | -- | --
|
||||||
40 | INCD | Increments the Data Pointer.
|
40 | INCD | Increments the Data Pointer.
|
||||||
@@ -103,38 +105,26 @@ The current implementation has Input 0 and Output 0 hooked to stdout and stdin r
|
|||||||
|
|
||||||
### Example Program: Hello World
|
### Example Program: Hello World
|
||||||
```
|
```
|
||||||
; Hello World for SplitBit CPU
|
; This is a basic hello world program for the SplitBit CPU.
|
||||||
; First, we define the string in Data Memory.
|
; We'll create a loop that outputs each byte of our string to Output 0, the text console.
|
||||||
Data:
|
|
||||||
0000 0x48 ; 'H'
|
|
||||||
0001 0x65 ; 'e'
|
|
||||||
0002 0x6C ; 'l'
|
|
||||||
0003 0x6C ; 'l'
|
|
||||||
0004 0x6F ; 'o'
|
|
||||||
0005 0x2C ; ','
|
|
||||||
0006 0x20 ; ' '
|
|
||||||
0007 0x57 ; 'W'
|
|
||||||
0008 0x6F ; 'o'
|
|
||||||
0009 0x72 ; 'r'
|
|
||||||
000A 0x6C ; 'l'
|
|
||||||
000B 0x64 ; 'd'
|
|
||||||
000C 0x32 ; '!'
|
|
||||||
000D 0x0A ; This is a linefeed, it's equivalent to putting '\n' in a string in C.
|
|
||||||
000E 0x00 ; Zero terminates the string.
|
|
||||||
|
|
||||||
; Next, we'll create a loop that outputs each byte of our string to Output 0, the text console.
|
#Program
|
||||||
Program:
|
|
||||||
0000 LDA 0x42 ; Load the first byte of the string into A.
|
Start:
|
||||||
0001 BRA 0x12 ; If A is zero, branch out of the loop.
|
LDA ; Load a byte of the string into A.
|
||||||
0002 0x00 0x00 ; The high byte of the branch.
|
BRA End ; If A is zero, branch out of the loop.
|
||||||
0003 0x0A 0x0A ; The low byte of the branch.
|
OUTA 0x00 ; Output the value in A to Port 0, the text console.
|
||||||
0004 OUTA 0xD1 ; Output the value in A.
|
INCD ; Increment the Data Pointer to the next byte of the string.
|
||||||
0005 0x01 0x00 ; The Output Port to use.
|
BRI Start ; Branch immediately to the start of the loop.
|
||||||
0006 INCD 0x40 ; Increment the Data Pointer to the next byte of the string.
|
|
||||||
0007 BRI 0x10 ; Branch immediately to the start of the loop.
|
End:
|
||||||
0008 0x00 0x00 ; The high byte of the branch address.
|
INIA 0x0A ; We'll load a linefeed into A and output it to make it look nice.
|
||||||
0009 0x00 0x00 ; The low byte of the branch address.
|
OUTA 0x00 ; Output it to the text console.
|
||||||
000A HALT 0xFF ; The end of the program.
|
HALT ; Terminate the program.
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
"Hello, World!"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Structure of a SplitBit Binary File:
|
### Structure of a SplitBit Binary File:
|
||||||
@@ -143,5 +133,5 @@ The Program and Data values are both stored in a single file for loading into th
|
|||||||
Here's an example hex dump of the hello world program stored in the proper format:
|
Here's an example hex dump of the hello world program stored in the proper format:
|
||||||
|
|
||||||
```
|
```
|
||||||
50 52 47 00 0A 42 12 00 0A D1 00 40 10 00 00 FF 44 41 54 00 0E 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 0A 00
|
50 52 47 00 0F 26 12 00 0A D1 00 40 10 00 00 28 0A D1 00 FF 44 41 54 00 0E 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 00
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user