-
Notifications
You must be signed in to change notification settings - Fork 0
/
phoenix_specs.txt
193 lines (127 loc) · 5.72 KB
/
phoenix_specs.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
=== OVERVIEW ===
- 8 bit data width
- has dedicated io ports
=== INSTRUCTIONS ===
0x00: NOP
0x01: MOV <reg>, <reg> -> move register into another register
0x02: LOD <reg>, <imm16> -> load 8 bit constant into register
0x03: OUT A <reg> -> output reg to address in A
0x04: INP <reg> A -> input address in A to reg
0x05: JNZ A -> jump to A register if nz is set
0x06: ADD <reg> <reg> -> add register into register and store the result into the left register
0x07: ADD <reg> <imm8> -> add const 8 bit value to register and store in reg
0x08: SUB <reg> <reg> -> subtract one register from another and save it to the left register
0x09: SUB <reg> <imm8> -> sub imm8 from reg and store in reg
0x0A: NAD <reg> <reg> -> bitwise nand
0x0B: NAD <reg> <imm8> -> bitwise nand
0x0C: NOR <reg> <reg> -> bitwise nor
0x0D: NOR <reg> <imm8> -> bitwise nor
0x0E: CMP <reg> <reg> -> compare reg to reg store result in fg
0x0F: CMP <reg> <imm8> -> compare reg to imm8 and store result in fg
0x10: JZR A -> jump to reg if zr flag is set
0x11: LDR <reg> A -> load one byte from address A into reg
0x12: WTR A <reg> -> writes one byte from register to address A
0x13 JMP A -> load A into pc
0x14 JEQ A -> jump if equals
0x15 JNQ A -> jump if not equals
0x16 JNZ B -> jump if not zero
0x17 JZR B -> jump if zero
0x18 JMP B -> jump to B
0x19 JEQ B -> jump if equals
0x1A JNQ B -> jump if not equals
0x1B: LDR <reg> B -> load one byte from address B into reg
0x1C: WTR B <reg> -> writes one byte from register to address B
0x1d: JMP <imm16> -> load imm16 into pc
0x1e: JEQ <imm16> -> jump if equals
0x1f: JNQ <imm16> -> jump if not equals
0x20: JZR <imm16> -> jump if zero
0x21: JNZ <imm16> -> jump if not zero
0x22: LAD A <imm16> -> load address
0x23: LAD B <imm16> -> load address
0x24: OUT B <reg> -> output reg to address in B
0x25: INP <reg> B -> input address in B to reg
0x26: IRE -> interrupt return
0x27: INT -> trigger int7 interrupt
=== INSTRUCTION ENCODING ===
A instruction has a fixed size of 24bit, and can never contain two imm8.
00000000 0000 0000 00000000
first 8bit = instruction
next 4bit = second optional register
next 4bit = first optional register
last 8bit = optional imm8
the register sections can be used as a high part for the imm8 to make it a imm16
=== HALTING THE CPU ===
the halt bit gets set if pc == 0xffff
=== REGISTERS ===
The cpu contains six general purpose registers (r0-r5), as well as one flag register (fg), and a program counter (pc)
r0 + r1 add to make the address A register and r2 + r3 add to make the address B register used in jmp's and memory accesses
0: r0 (8bit) -> AL
1: r1 (8bit) -> AH
2: r2 (8bit) -> BL
3: r3 (8bit) -> BH
4: r4
5: r5
-: fg (4bit)
-> bit 0: zero
-> bit 1: eq
-> bit 2: overflow
-> bit 3: halt
-: pc (16bit)
=== MEMORY LAYOUT ===
0x0000 - 0x7fff = general purpose rom
0x8000 - 0xffff = general purpose ram
=== STARTUP ===
Code execution starts at 0x0
=== I/O ===
The cpu can have multiple io ports. The following io ports exsist:
0x0: GPIO
=== GPIO ===
The Gpio port consists of 8 input and 8 output pins.
The value of the 8 input pins can be read using the inp instruction.
The value of the 8 output pins can be set using the out instruction.
The gpio pins do not need any configuration.
=== INTERRUPTS ===
when a interrupt is triggered the cpu jumps to 0x8000 (first address in ram).
The code execution can be continued using the ire (interrupt return instruction).
The interrupt handler needs to save the registers manually.
The interrupt will trigger when the current instruction finished executing.
When the execution of an interrupt begins a interrupt lock will be triggere witch masks all interrupts.
The lock gets released when the ire instruction is executed.
=== INTERRUPT CONTROLLER ===
The interrupt controller is located at 0xff00 in the io space.
the bits written to that address decide if the interrupt can be triggered.
reading from that io port will get the current interrupt id.
=== MICROCODE ===
The microcode is saved on multiple external eeproms or 1 eeprom with 32bit output.
All write instructions get executed on a falling edge to avoid write before read issues
Microcode commands:
PUT_A_ADDR: A -> address bus
PUT_IR0_DB: instruction reg 0 -> data bus
PUT_IR1_DB: instruction reg 1 -> data bus
SAVE_DB_IR0: data bus -> instruction reg 0
SAVE_DB_IR1: data bus -> instruction reg 1
PUT_IIMM_DB: instruction imm8 -> data bus
SAVE_DB_ALUA: data bus -> alu work reg A
SAVE_DB_ALUB: data bus -> alu work reg B
ALU_ADD: A + B -> OUT
ALU_CMP: if (A == B) 1 -> EQ else 0 -> EQ && if (A == 0) 1 -> Z else 0 -> Z
PUT_ALUOUT_DB: OUT -> data bus
COND_INVERT: 1 -> COND_INV
SAVE_PCB_IF_Z: if (if COND_INV !ZERO else ZERO) address bus -> pc buf and 1 -> cond
SAVE_PCB_IF_EQ: if (if COND_INV !EQ else EQ) address bus -> pc buf and 1 -> cond
SAVE_PCB: address bus -> pc buf
SAVE_DB_MEM: data bus -> ram/rom[address bus]
PUT_MEM_DB: ram/rom[address bus] -> data bus
PC_FLUSH: pc buf -> pc
PC_FLUSH_COND: if cond pc buf -> pc
ALU_SUB: A - B -> OUT
ALU_NAND: ~(A & B) -> OUT
ALU_NOR: ~(A | B) -> OUT
IO_IN: io[address bus] -> data bus
IO_OUT: data bus -> io[address bus]
PUT_IADR_ADDR: ir0 + ir1 + imm8 -> address bus
SAVE_ADDR_A: address bus -> A reg
SAVE_ADDR_B: address bus -> B reg
INT_RET_TO_ADDR: Interrupt return address -> address bus && resets interrupt controller int num && release interrupt lock
INT7_TRIGGER: 1 -> INT7
FINISH: start next instruction fetch / decode / execute cycle