Skip to content

Commit 59bf243

Browse files
committed
Merge remote-tracking branch 'wire-cpu/master'
1 parent 7f9885a commit 59bf243

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+24388
-1
lines changed

addon.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"git-hooks-pre-commit",
1616
"gitrid.sh",
1717
"LICENSE",
18-
"wiremod.*"
18+
"wiremod.*",
19+
"benchmark_*"
1920
]
2021
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//Wired Hello World!
2+
//Connect CPU membus input to console screen
3+
//Connect CPUs CLK input to button (toggle)
4+
//Notice how you can store your
5+
//subroutines/calls in DATA area
6+
jmp _code;
7+
message:
8+
db 'Hello World!',0;
9+
WriteString: //ESI - String pointer, EDX - Param
10+
mov eax,65536;
11+
AWriteLoop:
12+
cmp #esi,0; //Terminate on char 0
13+
je AEnd;
14+
mov #eax,#esi; //Output char
15+
inc eax;
16+
mov #eax,edx; //Output char param
17+
inc eax;
18+
inc esi;
19+
jmp AWriteLoop;
20+
AEnd:
21+
ret //Return from call
22+
23+
_code:
24+
mov esi,message;
25+
mov edx,000999; //White foreground on black background
26+
call WriteString;
27+
28+
//More about colors:
29+
//Lower 3 digits are foreground,
30+
//and higher 3 digits are background
31+
//Each of 3 digits shows amount of
32+
//RED, GREEN, and BLUE (in order)
33+
//Each color has 10 shades - from 0 to 9
34+
//
35+
//For example, 999044 will be dark yellow (044) on
36+
//a white background (999)
37+
//
38+
//Experiment with colors!
39+
//
40+
//Also, the 7th digit (if its not equal to 0) will
41+
//cause the character to blink by changing foreground and
42+
//background places (actual data in memory wont change)
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
This example assumes you are already familiar with ZASM
3+
as this will be going over advanced features.
4+
5+
For setup of this example:
6+
7+
1. Wire a button outputting value 32 to the Interrupt input on the CPU
8+
2. Connect CPU membus input to a console screen
9+
*/
10+
11+
DATA
12+
13+
/*
14+
Each external interrupt is 4 bytes
15+
formatted like so:
16+
Instruction Pointer, Code Segment, PTB, Flags
17+
Available flags are
18+
Bit 3(8) : Interrupt will set CMPR to 1, unavailable for external interrupts(they restore CMPR on EXTRET)
19+
Bit 4(16) : Interrupt will not set CS
20+
Bit 5(32) : Interrupt is enabled
21+
Bit 6(64) : Interrupt is external
22+
Bit 7(128): Interrupt will replace page table with PTB, which isn't restored on IRET/EXTRET
23+
Bit 8(256): Interrupt will replace number of page table entries with PTB, which isn't restored on IRET/EXTRET
24+
Bit 9(512): Interrupt will also push R0-R31 to stack, use EXTRETA instead of EXTRET to pop them
25+
26+
Flags can be combined, do this by adding the numbers together
27+
For example:
28+
8+32 = Interrupt is active, and on interrupt it will set CMPR to 1
29+
*/
30+
my_interrupt_table:
31+
ALLOC 32*4 // The interrupt table is 0 indexed
32+
DB my_external_interrupt,0,0,96 // so this is index 32
33+
DB my_internal_interrupt,0,0,32 // and this is index 33
34+
DB my_timer_interrupt,0,0,96 // Timer interrupts need to be external
35+
ALLOC 24*4 // Fill rest of space to 58 usable interrupts
36+
37+
external_int_str:
38+
DB "Hello from External Interrupt!",0
39+
40+
internal_int_str:
41+
DB "Hello from Internal Interrupt!",0
42+
43+
timer_int_str:
44+
DB "Hello from the Timer Interrupt",0
45+
46+
my_external_interrupt:
47+
CLI // Turn off the ability for another interrupt to happen
48+
CPUGET EDI,43 // get external memory and put it in EDI
49+
ADD EDI,60 // shift mem offset to start on line 2 of console screen
50+
MOV ESI,external_int_str
51+
external_int_strcpy: // Copy null terminated string
52+
MOV [EDI],[ESI]
53+
MCOPY 1
54+
MOV [EDI],999 // See helloworld.txt for more information about console colors
55+
INC EDI
56+
CMP [ESI],0
57+
JNE external_int_strcpy
58+
CLERR // Clear error code on CPU
59+
STI // Re-enable interrupts before returning from interrupt
60+
EXTRET // You need to use the EXTRET instruction for external interrupts, since IRET only pops IP and CS
61+
// EXTRET pops all 20 bytes from stack that are generated upon an external interrupt
62+
63+
my_internal_interrupt:
64+
// If CLI at start is not present, this interrupt can be interrupted
65+
// by another interrupt happening during execution.
66+
CPUGET EDI,43 // get external memory and put it in EDI
67+
MOV ESI,internal_int_str
68+
internal_int_strcpy: // Copy null terminated string
69+
MOV [EDI],[ESI]
70+
MCOPY 1
71+
MOV [EDI],999 // See helloworld.txt for more information about console colors
72+
INC EDI
73+
CMP [ESI],0
74+
JNE internal_int_strcpy
75+
CLERR // Clear error code on CPU
76+
IRET // Registers are not preserved in an internal interrupt, IRET only pops CS and IP to return to
77+
78+
my_timer_interrupt:
79+
CLI
80+
CPUGET EDI,43 // get external memory and put it in EDI
81+
ADD EDI,120 // shift mem offset to start on line 3 of console screen
82+
MOV ESI,timer_int_str
83+
timer_int_strcpy: // Copy null terminated string
84+
MOV [EDI],[ESI]
85+
MCOPY 1
86+
MOV [EDI],999 // See helloworld.txt for more information about console colors
87+
INC EDI
88+
CMP [ESI],0
89+
JNE timer_int_strcpy
90+
CLERR // Clear error code on CPU
91+
STI // re-enable interrupts
92+
EXTRET // Registers are not preserved in an internal interrupt, IRET only pops CS and IP to return to
93+
94+
95+
CODE
96+
STEF // Set the EXTENDED FLAG on, this allows you to call interrupts without halting CPU
97+
LIDTR my_interrupt_table // Load the interrupt table we have in memory
98+
CPUSET 52,59 // Set number of interrupts in table (defaults to 256)
99+
INT 33 // Call interrupt 33 to print to console screen.
100+
// Note that you can also call external interrupts internally using EXTINT (number)
101+
CPUSET 67,34 // Set timer interrupt(external interrupt #) to our timer interrupt
102+
CPUSET 65,4 // Set delay on timer to 4 seconds.
103+
CPUSET 64,1 // Set timer mode to seconds (it will read the 4 as 4 seconds, set to 2 to read as every 4 instructions)
104+
// Timer will now be running from here on.
105+
106+
wait_forever:
107+
INC R0
108+
JMP wait_forever
109+
// Use CLEF to disable the extended flag if you want to halt on error instead of handle
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
This example assumes you are already familiar with ZASM
3+
as this will be going over advanced features.
4+
5+
This will not go too indepth into how the paging
6+
system works, but instead focus primarily on the feature
7+
to call an interrupt on read or write of a specific page,
8+
to intercept memory requests and handle them internally.
9+
10+
Requires CPU memory model to be 8kb ram/rom or above.
11+
12+
For setup of this example:
13+
14+
1. Connect CPU membus input to a console screen
15+
*/
16+
17+
DATA
18+
interrupt_table:
19+
ALLOC 28*4 // fill interrupt space for 0-27
20+
DB read_mem,0,0,32 // Interrupt 28, called on a delayed memory read
21+
DB write_mem,0,0,32 // Interrupt 29, called on a delayed memory write
22+
ALLOC 1*4
23+
24+
page_table:
25+
ALLOC 16*2 // Entries for the paging table are 2 bytes each.
26+
27+
28+
// For more information on interrupts, read the interrupts example
29+
read_mem:
30+
CLI
31+
CLM // Disable paging features temporarily
32+
CPUGET ESI,63 // The requested address for the request
33+
CPUSET 27,[ESI] // Return the value in LADD
34+
CPUSET 42,4 // Set MEMRQ to 4 to signify read was handled
35+
STM // Reenable paging features after read is performed
36+
CLERR
37+
STI
38+
IRET
39+
40+
write_mem:
41+
CLI
42+
CPUGET EAX,27 // Get value requested for write
43+
CPUGET EDI,63 // Requested address for write
44+
CPUGET EDX,43 // Internal memory size
45+
SUB EDI,128*8 // Subtract page address from it
46+
MUL EDI,2 // Force position to be even(char pos)
47+
MOV ECX,EDI // Diagonal position
48+
MOV EBX,EDI // Horizontal Position
49+
MUL EDI,30 // Convert char pos to be line pos instead
50+
ADD ECX,EDI // Get diagonal position by adding line to char pos
51+
52+
// Print vertical character
53+
MOV [EDX:EDI],EAX
54+
INC EDI // On odd offsets we need to write color
55+
MOV [EDX:EDI],999 // write color to screen
56+
// Print horizontal character
57+
MOV [EDX:EBX],EAX
58+
INC EBX
59+
MOV [EDX:EBX],999
60+
// Print diagonal character
61+
MOV [EDX:ECX],EAX
62+
INC ECX
63+
MOV [EDX:ECX],999
64+
65+
CPUGET EAX,28 // Get LINT to check if we failed any memory I/O
66+
CMP EAX,29 // Check if we're in our own interrupt
67+
JNE shutdown
68+
CPUSET 42,5 // Set MEMRQ to 5 to signify write was handled
69+
CLERR
70+
STI
71+
IRET
72+
73+
shutdown:
74+
STI
75+
CLM
76+
CLEF
77+
INT EAX // repeat error now that we're not in extended mode
78+
79+
CODE
80+
STEF // Set extended flag for interrupt handling
81+
CPUSET 37,page_table // Load page table ptr into PTBL register
82+
CPUSET 38,16 // Set page table entries in PTBE register
83+
LIDTR interrupt_table
84+
85+
MOV EAX,0
86+
// Since only Readable/Writable/Executable are accessible via
87+
// the SPP Instruction, we have to manually create a permissions
88+
// mask for our new pages.
89+
90+
// Using SBIT isn't entirely necessary, to get the number below you can also
91+
// use the constant 232(calculated from 8+32+64+128)
92+
SBIT EAX,3 // (8) Read & Write calls int 28(read) and int 29(write)
93+
SBIT EAX,5 // (32) Readable
94+
SBIT EAX,6 // (64) Writable
95+
SBIT EAX,7 // (128) Executable
96+
ADD EAX,(256*2)
97+
// Runlevel can be obtained from the permission mask with floor(pmask/256)%256
98+
// To set the runlevel, add 256*runlevel to the permission mask
99+
MOV ECX,3 // Set 2 pages
100+
MOV EBX,7*2 // Starting from page 8
101+
ADD EBX,page_table
102+
103+
page_set_loop:
104+
MOV EDI,ECX
105+
MUL EDI,2
106+
MOV [EBX:EDI],EAX // Page byte 0 is the permission mask of the page
107+
INC EDI // Access page byte 1
108+
MOV [EBX:EDI],0 // Page byte 1 is the page this redirects to if the mapped flag is set
109+
LOOP page_set_loop
110+
111+
STM // Set Memory flag to enable memory paging features
112+
113+
/*
114+
Note that, unlike regular console screen prints
115+
this doesn't need to write character to even indexes
116+
and color to odd indexes, since those are both handled
117+
by interrupt 29(write_mem), so we can treat this like
118+
a regular section of memory.
119+
*/
120+
121+
MOV R0,128*8 // Get first index of page 8
122+
MOV ESI,str
123+
124+
print_loop:
125+
MOV [R0],[ESI]
126+
INC R0
127+
INC ESI
128+
CMP [ESI],0
129+
JNE print_loop
130+
131+
CLEF // Disable interrupt handling
132+
INT 2 // End execution.
133+
134+
str:
135+
DB "Hello Wiremod!",0
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
This example assumes you are already familiar with ZASM
3+
as this will be going over semi-advanced features.
4+
5+
Segment registers allow you to add an offset to memory access
6+
By default, they are all set to 0 on first startup of CPU
7+
and reset to 0 when the CPU is reset.
8+
9+
The available segment registers are
10+
CS - Code Segment, used to read instructions from RAM.
11+
It can only be changed with far jump instructions, trying to
12+
set it using other instructions results in an error of #13[1]
13+
14+
Setting this allows compiled programs using branches to run
15+
without having to be compiled knowing where they will sit in
16+
memory
17+
18+
SS - Stack Segment, this is where the stack starts from, stack access
19+
via PUSH, POP, RSTACK, SSTACK is relative to this segment
20+
21+
DS - Data Segment, default for all memory access instructions
22+
unless another segment is specified.
23+
24+
User Segments, none of these are used internally, so they can be used
25+
without fear of altering behavior outside of user programs which use
26+
these segments
27+
ES - Extra Segment
28+
GS - "G Segment"
29+
FS - "F Segment"
30+
KS - Key Segment
31+
LS - Library Segment
32+
*/
33+
34+
// Segment registers can be read and written to like any other register
35+
start:
36+
MOV DS,data_pos
37+
MOV R0,3
38+
MOV R1,[R0] // 3+data_pos, aka the fourth value, 720. Doesn't change R0
39+
// or DS in order to access and store the value in R1
40+
MOV R2,[0] // 0+data_pos, aka the first value, 640.
41+
JMP end_data_pos
42+
data_pos:
43+
DB 640,480
44+
DB 1280,720
45+
DB 0
46+
end_data_pos:
47+
48+
MOV R3,[CS:0] // Segment for access can be specified with SEG:Value
49+
MOV R4,[EAX:0] // and any register can be used as a segment
50+
MOV R5,R0:0 // This does nothing
51+
52+
/*
53+
LEA is one of the few instructions that use a user defined segment
54+
outside of memory access, and it writes the value of the address used
55+
by a memory access to the left hand side, it is effectively the same as
56+
57+
MOV EAX,R0 //(EAX is just a standin for an unused register)
58+
ADD EAX,DS //(or the segment explicitly defined instead of DS)
59+
MOV R7,EAX
60+
61+
^
62+
this code uses 6 bytes, where LEA uses:
63+
2 bytes(no segment supplied, register to register transfer I.E LEA R7,R0)
64+
3 bytes(segment supplied by user, register to register transfer I.E LEA R7,SS:R0)
65+
66+
*/
67+
68+
LEA R6,[R0] // This will put DS+R0 into R6 (data_pos+3)
69+
LEA R7,[SS:R0] // This will put SS+R0 into R7(SS+3)
70+
71+
/*
72+
Wire your CPU to a memory device
73+
and upload your own program to the device
74+
by clicking on it as if it were a CPU
75+
76+
If this example is uploaded to your CPU
77+
it will begin running the code on the
78+
memory device as if it were running on
79+
the original CPU, to debug the program
80+
press compile with your code open in the
81+
editor, afterward "Step Forward" will begin
82+
showing the proper lines.
83+
*/
84+
85+
CPUGET DS,43 // Get RAM size of CPU, aka the first byte of external memory.
86+
JMPF 0,DS // JMP to 0 + DS, setting CS to DS
87+
88+
/*
89+
Your program will now run from here until
90+
it errors or you reset it.
91+
*/

0 commit comments

Comments
 (0)