DP offset instructions, new demo programs.
Added DPUP and DPDN, which take a one byte operand specifying how far up or down to offset the Data Pointer. Three Fibonacci generators using the print.asm library. - 8 bit values printing in decimal representation. - 16 bit values printing in hexadecimal representation. - 32 bit values printing in hexadecimal representation.
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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"},
|
||||
|
||||
+38
-35
@@ -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:
|
||||
//
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user