Advertisement
Guest User

Untitled

a guest
May 24th, 2017
598
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.56 KB | None | 0 0
  1. At a glance, this is a vCPU with sixteen general purpose registers and a relatively
  2. minimal instruction set. The purpose of this vCPU is to allow microcontroller units that
  3. cannot execute instructions from RAM (this is very common, such as in the AVR and PIC
  4. microcontrollers) to achieve loading and running programs from a storage device without the
  5. need to reprogram the MCU itself. Because these MCUs cannot run code from RAM, an
  6. interpreter is necessary. The vCPU is a 16 bit CPU with 32 bit addressing modes. I chose
  7. this as the best compromise between a variety of factors; namely, allowing an 8-bit MCU to
  8. host this vCPU while not requiring an excessive amount of read/write cycles for every
  9. operation, allowing at least 256K RAM (for which at least 20 bit addressing modes are
  10. necessary), and giving benefit to running an interpreter for this vCPU on processors as wide
  11. as 32 bits (notably the ESP8266, which has become increasingly popular as of late). Many
  12. aspects of the vCPU are aimed at making the interpreter easy to implement on as many
  13. platforms as possible. For example, the vCPU has no concept of a system bus (unless you give
  14. it one); the vCPU simply reads and writes data to and from hardware devices in a way similar
  15. to the UNIX concept of "files" and expects the interpreter to know what to do with it. This
  16. even includes main memory. This makes it easier for the interpreter to store the vCPU's main
  17. memory in its own memory, or perhaps on a physical memory chip, or perhaps on an SD card
  18. over the SPI bus, or some combination of these methods. The vCPU doesn't care so long as it
  19. can read and write data to it. There's no need to do time-sensitive things like bit bashing
  20. a data bus from within the vCPU, which would be quite difficult. The interpreter only needs
  21. to provide the vCPU with a virtual device it can read and write to, then it can handle all
  22. the nuisances of real hardware on the real CPU.
  23.  
  24. +------------------------------------------------------------------------------------------+
  25. REGISTERS | Desc (Note: 16 bit word size)
  26. +------------------------------------------------------------------------------------------+
  27. 0x0 through 0xF | 16 general purpose registers (R0 through RF)
  28. 0x10 | Program Counter (PC)
  29. 0x11 | Flags (FF)
  30. 0x12 | Carry (CC)
  31. 0x13:0x14 | 32 bit Stack Pointer (SP)
  32. 0x15:0x16 | 32 bit Stack Base Pointer (BP)
  33. 0x17:0x18 | 32 bit Function Pointer for CALL and RET (FP)
  34. 0x19 | Hardware Protection Flags (PF)
  35. +------------------------------------------------------------------------------------------+
  36.  
  37. This vCPU is a Big Endian CPU. This makes the most sense when interpreting instructions
  38. from memory. If you're writing an interpreter, be mindful of endianness when forwarding
  39. a character stream from within the vCPU to a physical device that may expect little endian.
  40. This document also describes some aspects of the default assembler I will write for this
  41. vCPU. The next immediate goal after achieving a functional interpreter and assembler is to
  42. create a rudimentary C99 compiler for this vCPU architecture.
  43.  
  44. The vCPU supports three permission level rings of hardware protection, with additional
  45. memory protection mechanisms that must be implemented by the virtual CPU. See the interrupt
  46. table below.
  47.  
  48. +------------------------------------------------------------------------------------------+
  49. Hardware Protection Flags Register
  50. +------------------------------------------------------------------------------------------+
  51. Value | Ring | Desc
  52. +------------------------------------------------------------------------------------------+
  53. 0b0000000000000000 | Ring 0 | Kernel mode; full access to memory and all devices.
  54. 0b0000000000000001 | Ring 1 | Device driver mode; full access to some devices EXCEPT main
  55. | memory.
  56. 0b0000000000000011 | Ring 2 | User mode; no access to devices. Should only be allowed to
  57. | access its own stack (see interrupts). Implement syscalls
  58. | in ring 0 code for device access.
  59. ------------------ | Ring A | Ring Alpha - this is the interpreter. Considered a ring
  60. | because the interpreter has full access to memory, and
  61. | handles the actual hardware the vCPU interacts with, much
  62. | like a more typical device driver. The vCPU has no concept
  63. | of Ring Alpha, however.
  64. +------------------------------------------------------------------------------------------+
  65.  
  66. A note about Ring 1, device driver mode: ring 1 instructions may be given full access to
  67. all devices, but this is dangerous. Instead, define what devices the relevant ring 1
  68. instructions pertain to, and supply a whitelist of devices it may operate on. See the
  69. interrupt table below.
  70.  
  71. +------------------------------------------------------------------------------------------+
  72. INSTRUCTIONS | Legend: Ry | Destination register operand (y can be 0 through F)
  73. | Rx | Source register operand (x can be 0 through F)
  74. | D | Flag indicating if the address is 16 (0) or 32 (1) bits.
  75. | S | Nibble containing two flags. The most significant bit
  76. | | signifies whether to load/write into/from the most or
  77. | | least significant byte of a register. 0 = l = least
  78. | | significant, 1 = h = most significant. For example, RFh
  79. | | is the most significant byte of the Register RF. The
  80. | | least significant bit of S indicates if the address is
  81. | | 16 or 32 bits, the same way D does.
  82. | L | Preprocessor label pointing to a word at a 16 bit or 32 bit
  83. | | address. Labels may only point to words whose addresses
  84. | | are known at compile time; Otherwise, LOD and/or POP
  85. | | should be used to move the word into a register first.
  86. | | Alternatively, a literal number may be used instead of
  87. | | a label pointing to a word. Brackets denote when the
  88. | | word the label is pointing to should be used, rather
  89. | | than the value of the label pointer itself.
  90. | 8N | An 8 bit number. If prefixed with 0x, it's in hex.
  91. | 16N | Same as above, but 16 bits.
  92. | 32N | Same as above, but 32 bits.
  93. | RL | Register, Label, or Literal. Always assumed to be the value
  94. | | contained by the register or the value pointed to by
  95. | | the label if applicable.
  96. | ADR | An address of either 16 or 32 bits in length. Can be
  97. | | represented by a literal or a [label].
  98. +------------------------------------------------------------------------------------------+
  99.  
  100. These are the basic opcodes that define this virtual CPU. All instructions can be
  101. identified from the first byte. The total size in words can be identified from the second
  102. byte. When two registers are involved, the DESTINATION register will always be the upper
  103. nibble of a byte, and the SOURCE register will always be the lower nibble of a byte. When
  104. only one register is involved, the register will always be in the upper nibble.
  105. Note: # represents the maximum number of words in the instruction in the below table.
  106.  
  107. +------------------------------------------------------------------------------------------+
  108. Basic Opcodes (0x00 through 0xEF)
  109. +------------------------------------------------------------------------------------------+
  110. # | Code | Options | Mnemonic | Description
  111. +------------------------------------------------------------------------------------------+
  112. 1 | 0x00 | 0x00 | NOP | No Instruction
  113. - | ---- | ---- | SET Ry, RL | Preprocessor directive replaced by either SER or SEW
  114. | depending on if RL is a register, label, or literal.
  115. | (Aliases: MOV, CPY).
  116. 1 | 0x01 | 0xYX | SER Ry, Rx | Sets Ry to the value of Rx.
  117. 2 | 0x02 | 0xY0 0x16N | SEW Ry, L | Sets Ry to the literal or [label] value L.
  118. 1 | 0x03 | 0xYX | ADD Ry, Rx | Sets Ry to Ry+Rx. If an overflow occurs, Ry is set to
  119. | the least significant 16 bits, and CC is set to 1.
  120. | Otherwise, CC is 0.
  121. 1 | 0x04 | 0xYX | ADC Ry, Rx | Sets Ry to Ry+Rx+CC. CC is set to 0x0000.
  122. 1 | 0x05 | 0xYX | SUB Ry, Rx | Sets Ry to Ry-Rx. If an underflow occurs, CC is set
  123. | to 0x0001. Otherwise, CC is 0x0000.
  124. 1 | 0x06 | 0xYX | SBB Ry, Rx | Sets Ry to Ry-(Rx+CC). CC is set to 0x0000.
  125. 1 | 0x07 | 0xYX | MUL Ry, Rx | Sets Ry to Ry*Rx. If an overflow occurs, Ry is set to
  126. | the least significant 16 bits, and CC is set to the
  127. | most significant 16 bits. Otherwise, CC is 0.
  128. 1 | 0x08 | 0xYX | DIV Ry, Rx | Sets Ry to Ry/Rx. If Rx contains the value 0, Ry is
  129. | set to 0, and CC is set to 1. Otherwise CC is 0.
  130. | Results are rounded towards 0.
  131. 1 | 0x09 | 0xYX | MLS Ry, Rx | Same as MUL, but Ry and Rx are assumed to contain
  132. | signed numbers (two's complement).
  133. 1 | 0x0a | 0xYX | DVS Ry, Rx | Same as DIV, but Ry and Rx are assumed to contain
  134. | signed numbers.
  135. 1 | 0x0b | 0xYX | AND Ry, Rx | Sets Ry to Ry&Rx.
  136. 1 | 0x0c | 0xYX | BOR Ry, RX | Sets Ry to Ry|Rx. (Alias: OR)
  137. 1 | 0x0d | 0xYX | XOR Ry, Rx | Sets Ry to Ry^Rx.
  138. 1 | 0x0e | 0xYX | NOT Ry, Rx | Sets Ry to Ry~Rx.
  139. 1 | 0x0f | 0xYX | SHR Ry, Rx | Sets Ry to Ry>>Rx.
  140. 1 | 0x10 | 0xYX | SHL Ry, Rx | Sets Ry to Ry<<Rx
  141. 1 | 0x11 | 0xYX | ASR Ry, Rx | Sets Ry to Ry>>>Rx (logical shift for signed values).
  142. 1 | 0x12 | 0xYX | ASL Ry, Rx | Sets Ry to Ry<<<Rx.
  143. 2 | 0x13 | 0xYX | ROR Ry, Rx | Sets the 15 least significant bits of Ry to Ry>>Rx,
  144. | and the most significant bit of Ry to what was
  145. | formerly the least significant bit of Ry.
  146. 2 | 0x14 | 0xYX | ROL Ry, Rx | Sets the 15 most significant bits of Ry to Ry<<Rx,
  147. | and the least significant bit of Ry to what was
  148. | formerly the most significant bit of Ry.
  149. - | ---- | ---- | CLR Ry | Preprocessor directive that replaces “CLR Ry” with
  150. | “XOR Ry, Ry”.
  151. 3 | 0x15 | 0xYD 0xADR | LOD Ry, ADR | Load a word from the address ADR into Ry.
  152. 3 | 0x16 | 0xYD 0xADR | STR Ry, ADR | Store a word from Ry in the address ADR.
  153. 3 | 0x17 | 0xYS 0xADR | LDB Ry, RLS | Reads the most or least significant byte (denoted by
  154. | S) from the word at the address RL into the least
  155. | significant byte of Ry.
  156. 3 | 0x18 | 0xYS 0xADR | STB Ry, RLS | Writes the least significant byte of Ry into the
  157. | most or least significant byte (denoted by S) of
  158. | the word at address RL.
  159. - | ---- | ---- | CMP Ry, RL | Compare Ry to RL. If they're equal, FF is set to 0x00.
  160. | If Ry is greater than RL, FF is set to 0x01.
  161. | If Ry is less than RL, FF is set to 0x02.
  162. | Replaced by CMR or CMW depending on if RL is a
  163. | register, label, or literal. Values are assumed to
  164. | be unsigned.
  165. 1 | 0x19 | 0xYX | CMR Ry, Rx | Compare Ry to Rx.
  166. 2 | 0x1a | 0xY0 0x16N | CMW Ry, L | Compare Ry to a 16 bit literal or [label].
  167. - | ---- | ---- | CMS Ry, RL | Compare Ry to RL assuming signed values. Preprocessor
  168. | directive replaced by CSR or CSW depending on if RL
  169. | is a register, literal, or [label]. (Alias: CMPS).
  170. 1 | 0x1b | 0xYX | CSR Ry, Rx | Compare Ry to Rx assuming signed values.
  171. 2 | 0x1c | 0xY0 0x16N | CSW Ry, L | Compare Ry to a literal or [label] assuming signed
  172. | values.
  173. - | ---- | ---- | CUS Ry, RL | Compare Ry, assuming it is signed, to RL, which is
  174. | assumed to be unsigned. Replaced by CUR or CUW
  175. | depending on RL type. (Alias: CMPUS).
  176. 1 | 0x1d | 0xYX | CUR Ry, Rx | Compare Ry to Rx assuming Ry is signed, and Rx is not.
  177. 2 | 0x1e | 0xY0 0x16N | CUW Ry, L | Compare Ry (signed) to an unsigned literal or [label].
  178. 3 | 0x1f | 0x0D 0xADR | JMP ADR | Unconditional jump of PC to the 32 bit address A.
  179. 3 | 0x20 | 0xYX | JMA Ry, Rx | Unconditional jump of PC to the 32 bit address held in
  180. | Ry:Rx. Can be combined with other jumps to jump to
  181. | arbitrary points in memory not known at compile time
  182. | (Aliases: JMPADR, JMPA, JAM).
  183. 3 | 0x21 | 0x0D 0xADR | JIE ADR | Jump to 32 bit address 32N if the value of FF
  184. | indicates the previous comparison resulted in an
  185. | equal flag. (Alias: JE).
  186. 3 | 0x22 | 0x0D 0xADR | JNE ADR | Jump if not equal to.
  187. 3 | 0x23 | 0x0D 0xADR | JIG ADR | Jump if greater than.
  188. 3 | 0x24 | 0x0D 0xADR | JIL ADR | Jump if less than.
  189. 3 | 0x25 | 0x0D 0xADR | JLE ADR | Jump if less than or equal to.
  190. 3 | 0x26 | 0x0D 0xADR | JGE ADR | Jump if greater than or equal to.
  191. 3 | 0x27 | 0x0D 0xADR | JIC ADR | Jump if CC does not equal 0. (Alias: JC).
  192. 3 | 0x28 | 0x0D 0xADR | JNC ADR | Jump if CC is equal to 0x0000 (0).
  193. 3 | 0x29 | 0x0D 0xADR | CAL ADR | Same as jump, but the current PC is stored in FP.
  194. | (Alias: CALL)
  195. 1 | 0x2a | 0x00 | RET | Same as jump, but the address is retrieved from FP.
  196. 2 | 0x2b | 0xY0 | INC Ry | Increments the value of Ry by 1. Overflow is handled
  197. | the same way as ADD.
  198. 2 | 0x2c | 0xY0 | DEC Ry | Decrements the value of Ry by 1. Underflow is handled
  199. | the same way as SUB.
  200. 2 | 0x2d | 0xY0 | PSH Ry | Pushes the value in Ry onto the stack at SP+BP, then
  201. | increments BP by 1.
  202. 2 | 0x2e | 0xY0 | POP Ry | Retrieves the value located at SP+BP in Ry, then
  203. | decrements BP by 1.
  204. 1 | 0x2f | 0xYX | SBP Ry, Rx | Sets the stack base pointer to Ry:Rx.
  205. 1 | 0x30 | 0xYX | LBP Ry, Rx | Sets Ry to the MSB of BP and Rx to the LSB of BP.
  206. 1 | 0x31 | 0xYX | SSP Ry, Rx | Sets the stack pointer to Ry:Rx.
  207. 1 | 0x32 | 0xYX | LSP Ry, Rx | Sets Ry to the MSB of SP and Rx to the LSB of SP.
  208. 2 | 0x33 | 0xYX 0x16N | LAD Ry,Rx,L | Sets Ry:Rx to SP+BP+L, assuming L is a signed number.
  209. | (Alias: LADR, LODADR).
  210. 2 | 0xEF | 0x00 0x16N | SYS L | Call the system to perform a function. The syscall
  211. | table is defined by the OS, if there is one. Only
  212. | literals should be used here.
  213.  
  214. +- Ring 0 only (0xF0 through 0xFE) --------------------------------------------------------+
  215.  
  216. 1 | 0xF0 | 0xYX | LFP Ry, Rx | Sets Ry to the MSB of FP and Rx to the LSB of FP.
  217. 1 | 0xF1 | 0xYX | SFP Ry, Rx | Sets the function pointer to Ry:Rx.
  218. 3 | 0xF2 | 0x0D 0xADR | SVR ADR | Save all registers to a buffer at address ADR.
  219. 3 | 0xF3 | 0x0D 0xADR | RSR ADR | Restore all registers from a buffer at address ADR.
  220.  
  221. +- Ring 0/1 only (0xFF) -------------------------------------------------------------------+
  222.  
  223. 1 | 0xFF | 0x00 | INT | Send the interpreter an interrupt. See the interrupt
  224. | table below.
  225. +------------------------------------------------------------------------------------------+
  226.  
  227. The main purpose of interrupts is to gain basic functionality (write characters to the
  228. screen, read input from the keyboard, etc.) from the interpreter. These can only be invoked
  229. in ring 0 or 1 mode; user mode programs should use syscalls. All interrupts return 0x0000 to
  230. R0 upon success, or 0xFFFF as a generic error (more specific error codes may be returned as
  231. well).
  232.  
  233. +------------------------------------------------------------------------------------------+
  234. Software Interrupts
  235. +------------------------------------------------------------------------------------------+
  236. Register 0 | Other Registers | Desc
  237. +------------------------------------------------------------------------------------------+
  238.  
  239. NO COMMAND
  240. 0x0000 | | No command.
  241.  
  242. PAUSE
  243. 0x0001 | R1: Time in seconds | Pauses the vCPU for (R1*1000)+R2 milliseconds.
  244. | R2: Time in milliseconds | Timing is not guarenteed to be perfect.
  245.  
  246. WRITE TO DEVICE
  247. 0x0002 | R1: Pointer to buffer (MSB) | Writes bytes from a buffer at R1:R2 of length
  248. | R2: Pointer to buffer (LSB) | R3 to the device R4 at position R5:R6.
  249. | R3: Length of buffer | Positioning is always absolute.
  250. | R4: Device ID |
  251. | R5: Position (MSB) |
  252. | R6: Position (LSB) |
  253.  
  254. READ FROM DEVICE
  255. 0x0003 | R1: Pointer to buffer (MSB) | Reads R3 bytes into a buffer at R1:R2 from
  256. | R2: Pointer to buffer (LSB) | device R4 at position R5:R6.
  257. | R3: Length of buffer | Positioning is always absolute.
  258. | R4: Device ID |
  259. | R5: Position (MSB) |
  260. | R6: Position (LSB) |
  261.  
  262. RUN AS RING
  263. 0x0004 | R1: Function pointer (MSB) | Jump to address R1:R2 automatically after
  264. | R2: Function pointer (LSB) | R5:R6 instructions are performed. Useful for
  265. | R3: Ring (0-2) | both multiprogramming and hardware protection.
  266. | R4: Device ID | Once R5:R6 instructions have been executed, the
  267. | R5: Instruction count (MSB) | real address is stored in FP, and PF is
  268. | R6: Instruction count (LSB) | returned to the ring it was prior.
  269. | R7: Pointer to buffer (MSB) | If this is called from Ring 1, only 1 or 2 are
  270. | R8: Pointer to buffer (LSB) | valid values for R3. Invalid values always
  271. | | result in ring 2 (usermode).
  272. | | If R3 is ring 1, R7:R8 may optionally point to
  273. | | a buffer containing the device IDs of only
  274. | | the devices the following instructions are
  275. | | allowed to operate on. Use this to prevent
  276. | | possibily malicious ring 1 instructions from
  277. | | accessing devices it is not intended to. If
  278. | | R8 is 0x0000, full access is assumed (!).
  279. | | This may only be triggered once from each ring
  280. | | until address R1:R2 is jumped back to.
  281. | | Subsequent triggerings of this interrupt are
  282. | | ignored until R1:R2 is jumped back to.
  283.  
  284. GET DESCRIPTOR
  285. 0x0005 | R1: Pointer to buffer (MSB) | Get the descriptor of a device. The supplied
  286. | R2: Pointer to buffer (LSB) | buffer at R1 must be at least 255 bytes large.
  287. | R3: Device ID | The first three bytes are a 16 bit ID followed
  288. | | by a terminating zero, followed by an ASCII
  289. | | human-readable description of the device.
  290.  
  291. SET GFX MODE
  292. 0x0006 | R1: Pointer to buffer (MSB) | Sets the graphics mode of the interpreter. See
  293. | R2: Pointer to buffer (LSB) | graphic modes table below. Returns 0x0001 to
  294. | R3: Graphics mode | R0 if an out of memory error occurs, 0x0002 if
  295. | | an error reading the buffer occurs, and 0x0003
  296. | | if the GFX mode isn't supported by the screen.
  297. | | If the GFX mode doesn't require a buffer, R1:R2
  298. | | is ignored.
  299.  
  300. UPDATE DEVICE
  301. 0x0007 | R1: Device ID | Requests the device to update. Depending on the
  302. | | device, this may be ignored.
  303.  
  304. DEFINE SYSCALLS
  305. 0x0008 | R1: Pointer to buffer (MSB) | Defines the syscall table by pointing to a
  306. | R2: Pointer to buffer (LSB) | buffer of function pointers. See syscall buffer
  307. | | format entry below. The buffer must stay in
  308. | | memory.
  309.  
  310. REDIRECT MEMORY
  311. 0x0009 | R1: 32 bit address (MSB) | Redirect calls to main memory while in usermode
  312. | R2: 32 bit address (LSB) | to another device and/or address. Makes virtual
  313. | R3: Device ID | memory easy. Does not apply to ring 0.
  314. | | Set R1:R2 to 0x00000000 and R3 to 0x0000 to
  315. | | stop redirecting memory.
  316. | | Note that ring 1/2 code will not be aware of a
  317. | | difference.
  318.  
  319. PROTECT MEMORY
  320. 0x000a | R1: 32 bit address (MSB) | Set an acceptable memory address range for use
  321. | R2: 32 bit address (LSB) | while in ring 2. Note that this corresponds
  322. | R3: Device ID | to the REAL addresses, not the redirected
  323. | R4: 32 bit address (MSB) | addresses usermode instructions would access
  324. | R5: 32 bit address (LSB) | while memory redirection is in use. A usermode
  325. | | program attempting to address memory outside of
  326. | | this range will cause a segmentation fault.
  327.  
  328. SCALE IMAGE
  329. 0xFFFC | R1: Pointer to buffer (MSB) | Speed hack requesting the host CPU scale an
  330. | R2: Pointer to buffer (LSB) | image defined in a buffer at R1:R2 from size
  331. | R3: Source width | R3xR4 to size R5xR6, and store the result
  332. | R4: Source height | in a buffer at R7:R8. No interpolation is
  333. | R5: Target width | used.
  334. | R6: Target height |
  335. | R7: Pointer to buffer (MSB) |
  336. | R8: Pointer to buffer (LSB) |
  337.  
  338. BLIT IMAGE
  339. 0xFFFD | R1: Pointer to buffer (MSB) | Speed hack requesting the host CPU blit an
  340. | R2: Pointer to buffer (LSB) | image of size R3xR4 onto the screen buffer at
  341. | R3: Width | R5xR6. Because alpha colors are not defined in
  342. | R4: Height | any RGB format below, an alpha color of up to
  343. | R5: X | 24 bits may be defined in R7:R8. If a color
  344. | R6: Y | palette is being used rather than RGB, just use
  345. | R7: Alpha Color (MSB) | R8. The image buffer is located at R1:R2.
  346. | R8: Alpha Color (LSB) | R5 (X) and R6 (Y) are assumed to be signed.
  347.  
  348. DRAW TRIANGLE
  349. 0xFFFE | R1: Pointer to buffer (MSB) | Speed hack requesting the host CPU draw and
  350. | R2: Pointer to buffer (LSB) | blit a triangle defined in the buffer at R1:R2
  351. | R3: Color (MSB) | filled with the color defined in R3:R4. Like
  352. | R4: Color (LSB) | above, R3:R4 can be a color of up to 24 bits
  353. | | in depth, or R4 can reference a palette color.
  354.  
  355. DRAW TEXTURED TRIANGLE
  356. 0xFFFF | R1: Pointer to buffer (MSB) | Like above, but a textured triangle with the
  357. | R2: Pointer to buffer (LSB) | texture located at buffer R3:R4.
  358. | R3: Pointer to buffer (MSB) |
  359. | R4: Pointer to buffer (LSB) |
  360. +------------------------------------------------------------------------------------------+
  361.  
  362. Character streams to and from the vCPU are all handled by the interpreter. Programs
  363. inside the vCPU shouldn't have any concept of a system bus. Apart from the following hard-
  364. coded values, it is up to interpreter to identify external hardware and deliver the vCPU
  365. a device ID that programs can interpret. Note: only relevant in kernel mode; if an OS is
  366. running inside the vCPU, typical UNIX "files" should be provided by the vCPU.
  367.  
  368. +------------------------------------------------------------------------------------------+
  369. Device Table
  370. +------------------------------------------------------------------------------------------+
  371. Device ID | Description (253 character max)
  372. +------------------------------------------------------------------------------------------+
  373. 0x0000 | MAIN MEMORY
  374. 0x0001 | SCREEN BUFFER
  375. 0x0002 | KEYBOARD INPUT QUEUE
  376. 0x0003 | ACTIVE INPUTS
  377. 0x....
  378. 0x...n | Free device input slots.
  379. +------------------------------------------------------------------------------------------+
  380.  
  381. MAIN MEMORY is as it sounds; it is the primary memory, usually RAM, presented to the
  382. vCPU. It can be read from and written to via interrupts in kernel mode if desired; useful
  383. for writing entire buffers rather than single words. Just keep in mind that memory is seen
  384. by the vCPU in words (2 bytes), while a buffer is a linear array of single bytes; be mindful
  385. of word alignment and leading zeroes.
  386. The SCREEN BUFFER is a linear array pixels (refer to pixel format table below) that can
  387. be written to display something on the screen. After writing data to the screen buffer,
  388. trigger the update device interrupt to swap it out of the buffer and onto the screen.
  389. The KEYBOARD INPUT QUEUE contains up 32 of the last ASCII keys pressed by the keyboard,
  390. in the order of First In, First Out. Once this device is read, the keys are cleared.
  391. ACTIVE INPUTS is to make real-time input easier. When read at any given time, it will
  392. contain up to sixteen ASCII characters that are currently pressed on the keyboard. Getting
  393. input through other fashions is perfectly possible through the KEYBOARD INPUT QUEUE or
  394. custom devices not provided by default.
  395.  
  396. As far as the vCPU is concerned, the screen is always just a linear array of bytes to
  397. write to. It's the interpreters job to turn that into an actual display. The interpreter
  398. handles VRAM; this makes it easier for the vCPU to switch modes without having to reboot.
  399. However, keep in mind, the interpreter may choose to reserve a portion of main memory for
  400. VRAM iF there is no external VRAM available. This may result in out-of-memory errors;
  401. programs in the vCPU should be prepared to handle this if they cannot guarentee enough
  402. memory is free.
  403. The equation for the size of the screen buffer is simply Width*Height*ColorDepth, where
  404. Width and Height are in pixels, and ColorDepth is the number of bytes it takes to represent
  405. a single pixel (or in some graphic modes, a single character).
  406.  
  407. +------------------------------------------------------------------------------------------+
  408. Graphic modes
  409. +------------------------------------------------------------------------------------------+
  410. R3 | Desc
  411. +------------------------------------------------------------------------------------------+
  412. 0x0000 | No display.
  413.  
  414. 0x0001 | 40x30 Character Display mode.
  415. | The screen buffer device becomes a linear array of 1,200 bytes (ASCII expected)
  416. | that are used to create a 40x30 ASCII character display. Therefore, the 0th
  417. | byte is the character cell at position (0,0), the 20th byte is the character
  418. | cell at (20,0), the 40th byte is the character cell at (0,1), and so on. Thus
  419. | the equation to access any arbitrary character cell is Position=(Y*Width)+X.
  420. | In this case, the width is 40, and X may be no greater than 29 (since we start
  421. | at 0). The screen buffer works the same way in all graphic modes, except the
  422. | width and height of the screen may vary, and pixels of a particular format
  423. | are expected as opposed to ASCII characters.
  424.  
  425. 0x0002 | Variable Resolution Character Display mode. Supply a buffer of two words (four
  426. | bytes), where the first word defines the width in characters and the second
  427. | word defines the height in characters. This buffer does not need to remain in
  428. | memory after the interrupt is triggered.
  429.  
  430. 0x0003 | 320x200 16 color mode. A buffer of 48 bytes should be supplied to define a
  431. | 16 color palette. Each color consists of three bytes (one red, one green, one
  432. | blue) (16*3=48). Note that this buffer must remain in memory so long as the
  433. | vCPU is in this graphics mode. 320x200 was chosen for a few reasons, namely for
  434. | compatibility with VGA, and the ability to fit the palette and screen buffer
  435. | in the upper 32k of memory, thus reducing the number of read/write cycles
  436. | needed to access it. This mode is best for 8-bit host CPUs.
  437.  
  438. 0x0004 | 320x240 16 color mode. Same as above but with extra vertical resolution. Best
  439. | for displays that have accessible VRAM, so a screen buffer doesn't have to be
  440. | kept in main memory. For example, screens with an ILI9340 driver have static
  441. | RAM accessible via SPI for this purpose.
  442.  
  443. 0x0005 | 320x200 256 color mode. Similar to above, a buffer of 256*3 (768) bytes should
  444. | be supplied to define a color palette. 320x200 was chosen for VGA compatibility
  445. | and the ability to keep a screen buffer and palette in the upper 64k of memory.
  446.  
  447. 0x0006 | 320x240 256 color mode. Like the other 320x240 mode, this is best used with
  448. | external VRAM.
  449.  
  450. 0x0007 | Variable resolution 16 color mode. A 52 byte buffer should be provided; the
  451. | first word (2 bytes) defines the horizontal resolution, and the second word
  452. | defines the the vertical resolution. The remaining 48 bytes are a color palette
  453. | define the same way as other 16 color modes.
  454.  
  455. 0x0008 | Variable resolution 256 color mode. A 772 byte buffer should be provided; like
  456. | above, the first two words (four bytes) define the resolution, and the
  457. | remaining 768 bytes define the 256 color palette.
  458.  
  459. 0x0009 | Variable resolution 8-bit RGB color mode. A four byte buffer should be provided
  460. | defining the resolution, with the most significant two bytes representing the
  461. | horizontal resolution, and the least significant two bytes representing the
  462. | vertical resolution. Unlike the color palette buffers, this buffer does not
  463. | need to remain in memory, as the interpreter will store it.
  464.  
  465. 0x000a | Variable resolution 16-bit RBG color mode. Supply a four byte buffer defining
  466. | the resolution, like above.
  467.  
  468. 0x000b | Variable resolution 24-bit RGB color mode. Supply a four byte buffer defining
  469. | the resolution, like above.
  470.  
  471. +------------------------------------------------------------------------------------------+
  472.  
  473. The below pixel formats define how pixels should be represented within buffers for given
  474. graphic modes.
  475.  
  476. +------------------------------------------------------------------------------------------+
  477. Pixel formats
  478. +------------------------------------------------------------------------------------------+
  479. Mode | Format
  480. +------------------------------------------------------------------------------------------+
  481. 16 color modes | 1 byte represents two pixels mapped to a 3 byte RGB color palette.
  482. | The most signifcant nibble represents the first pixel, the least
  483. | signifcant the second.
  484.  
  485. 256 color modes | 1 byte represents one pixel mapped to a 3 byte RGB color palette.
  486.  
  487. 8-bit RGB modes | 1 byte represents one RGB pixel. The first three bits are the red value,
  488. | the second three bits are the green value, and the last two bits are the
  489. | blue value.
  490.  
  491. 16-bit RGB modes | 2 bytes (one word) represent one RGB pixel. The first six bits are red,
  492. | the next five are green, and the last five are blue.
  493.  
  494. 24-bit RGB modes | 3 bytes represent one RGB pixel. The first byte represents the red value,
  495. | the second green, and the third blue.
  496. +------------------------------------------------------------------------------------------+
  497.  
  498. To use the speed hack interrupts for triangle drawing, the triangles must be defined in
  499. one of the formats below. All X and Y values (including those for UVs) are assumed to be
  500. signed. Note that the triangles do not have a Z dimension; if 3D triangles are to be used,
  501. the projection matrix must already be applied.
  502.  
  503. +------------------------------------------------------------------------------------------+
  504. Triangle formats
  505. +------------------------------------------------------------------------------------------+
  506. Type | Desc
  507. +------------------------------------------------------------------------------------------+
  508. Untextured Triangle | One word (two bytes) for X, and one word for Y define each vertex.
  509. | This results in a buffer of 12 words (24 bytes).
  510.  
  511. Textured triangle | One word for X, one word for Y, one word for UVx, one word for UVy
  512. | define each vertex and its texture mapping. This results in a buffer
  513. | of 24 words (48 bytes).
  514. +------------------------------------------------------------------------------------------+
  515.  
  516. +------------------------------------------------------------------------------------------+
  517. Syscall table buffer format
  518. +------------------------------------------------------------------------------------------+
  519. The syscall table buffer is simply a collection of 32 bit function pointers. Each syscall's
  520. number will then correspond to the 32 bit index of the function pointer. For example,
  521. syscall 0 will be the function pointer starting at byte 0, syscall 1 will be the function
  522. pointer starting at byte 4 (32 bit index 1), syscall 2 will be the function pointer starting
  523. at byte 8 (32 bit index 2), and so on. It is up to the OS to define how information should
  524. be passed when these functions are called.
  525. +------------------------------------------------------------------------------------------+
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement