Permalink
Cannot retrieve contributors at this time
2093 lines (1609 sloc)
92.8 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| YCPU Specification | |
| Version 0.9 RELEASE CANDIDATE | |
| ### Table of Contents ########################################################## | |
| 1. Introduction | |
| 1.A. Public Domain Dedication | |
| 2. Instruction Set Overview | |
| 3. Hardware Information | |
| 3.A. Registers | |
| 3.B. Supervisor/User Modes | |
| 3.C. Hardware Devices | |
| 3.D. Interrupts | |
| 3.E. Addressing Modes | |
| 3.F. Memory Management | |
| 3.G. Boot Sequence | |
| 3.H. The Real Time Clock | |
| 3.I. Switching Context | |
| 4. Instruction Set Description | |
| 4.A. Bit Patterns | |
| 4.B. ALU Instructions | |
| 4.C. Bit Shifting Instructions | |
| 4.D. Bit Testing Instructions | |
| 4.E. Branch Instructions | |
| 4.F. Increment Instructions | |
| 4.G. Jump & Call Instructions | |
| 4.H. Stack Instructions | |
| 4.I. Processor Function Instructions | |
| 5. History | |
| ### 1. Introduction ############################################################ | |
| The YCPU Specification describes a 16-bit processor architecture with a | |
| comprehensive instruction set and features. These features include: | |
| * eight general purpose 16-bit data/address registers; | |
| * user/supervisor modes with different privileges and stack pointers; | |
| * memory segmentation with resizable segments for code, stack, interrupts, | |
| and two data segments; | |
| * memory protection with not-present/read-only attributes; | |
| * 28 bits of address space for memory access; | |
| * real time clock with a programmable timer that raises interrupts; | |
| * hardware bus that supports up to 15 devices with 24 bits of address space | |
| each. | |
| This document is made up of four sections. Each section describes the YCPU | |
| Specification in increasing detail. This first section includes a brief overview | |
| of the document and the public domain dedication. In brief, the specification | |
| document is released to the public domain, and anyone may use it for any purpose | |
| without permission or attribution. | |
| Section 2 gives a broad overview of the 58 instructions that you can use to | |
| write programs for the YCPU. The instructions are divided by function into | |
| groups: math (2.A.), increment (2.B.), bit-shifting (2.C.), bit-testing (2.D.), | |
| branch (2.E.), jump (2.F.), stack (2.G.), and processor function (2.H.). | |
| Section 3 describes the processor functions in great detail. Specifically, this | |
| section describes the processor's registers (3.A.), the supervisor/user | |
| modes (3.B.), Hardware devices and input/output, (3.C.), interrupts and fault | |
| states and how to handle them (3.D.), the six memory addressing modes (3.E.), | |
| memory management and the use of segments (3.F.), the processor's boot | |
| sequence (3.G.), the real time clock (3.H.), and how to switch context (3.I.). | |
| Section 4 details how instructions are encoded into 16-bit program words, as | |
| well as the exact function of every instruction, including how these functions | |
| effect memory and flags. | |
| === 1.A. Public Domain Dedication ============================================== | |
| This document is dedicated to the public domain under the terms of the Creative | |
| Commons Zero (CC0) waiver. All rights have been waived with regard to | |
| copyright law, including all related and neighboring rights, to the extent | |
| allowed by law. | |
| You can copy, modify, and distribute this document, and use it to create | |
| derivative works, even for commercial purposes, all without asking permission. | |
| More information about CC0 waiver is available online at: | |
| http://creativecommons.org/about/cc0 | |
| ### 2. Instruction Set Overview ################################################ | |
| This section contains a brief overview of all instructions that can be used when | |
| programming the YCPU. For more information about specific processor functions, | |
| please reference Section 3., Hardware Information. For detailed information on | |
| how these instructions are encoded, please reference Section 4., Instruction | |
| Set Description. | |
| These instructions often change the value of the eight general purpose | |
| registers, which are named r0, r1, r2, r3, r4, r5, r6, and r7. Assemblers should | |
| also accept the names A, B, C, D, W, X, Y, and Z for these registers. | |
| === 2.A. Math Instructions ==================================================== | |
| At its heart, the YCPU is a fast math processor. It handles both signed and | |
| unsigned multiply and divide instructions, and has a carry flag so that you can | |
| chain 16-bit additions and subtractions. For more information about these | |
| instructions, including when flags are set, reference 4.B. | |
| The format of math instructions is: | |
| XXX R, M | |
| XXX is the three-letter instruction code (ex. "ADC" or "MUL"). All math | |
| instructions are either 8-bit or 16-bit. The default action is 16-bit | |
| math. You can specify a 8-bit instruction by adding the text ".8" to | |
| the end of XXX (ex. "ADC.8 RX, RY" or "MUL.8 RX, RY"). | |
| R is a register with the value of R0, R1, R2, R3, R4, R5, R6, or R7. R | |
| designates the first operand of the math instruction, and is also the | |
| destination of the result of the math instruction. | |
| M is a register or memory location that designates the second operation of | |
| the math operation. You can access memory with these addressing modes: | |
| Addressing Mode Syntax Value is... | |
| Immediate $1234 Value of Next Word | |
| Absolute [$1234] Mem[Next Word] | |
| Register RX Value of Register (R0 ... R7) | |
| Indirect [RX] Mem[R] | |
| Indirect Offset [RX,$1234] Mem[R + Next Word] | |
| Indirect Indexed [RX,RX] Mem[R+R] At least one register | |
| must be R4, R5, R6, or R7. | |
| The math instructions are: | |
| ADC R = R + M Adds M to R, with carry (if carry flag is set, add 1). | |
| ADD R = R + M Adds M to R, ignoring carry. | |
| AND R = R & M Bitwise and. | |
| CMP R = R Compares R and M and sets flags based on results. | |
| DIV R = R / M Unsigned division. | |
| DVI R = R / M Signed division. | |
| EOR R = R ^ M Bitwise exclusive or. | |
| LOD R = M Sets R equal to value of M. | |
| MDI R = R % M Signed modulus. | |
| MLI R = R * M Signed multiply, 32-bit result: High 16-bits of result | |
| are stored in R0. If R is R0, R0 will equal that low | |
| 16-bits of the result, and the high 16-bits are lost. | |
| MOD R = R % M Unsigned moduls. | |
| MUL R = R * M Unsigned multiply. As with MLI, the high 16-bits of the | |
| the result are stored in R0, and may be overwritten. | |
| NEG R = 0 - M Bitwise negation. | |
| NOT R = !M Bitwise NOT. | |
| ORR R = R | M Bitwise OR. | |
| STO M = R Sets M equal to R. | |
| SBC R = R - M Subtracts M from R, with carry. | |
| SUB R = R - M Subtracts M from R, ignoring carry. | |
| === 2.B. Increment Instructions =============================================== | |
| Increment instructions allow you to add or subtract small values from the | |
| registers. These instructions are faster and smaller than math instructions. | |
| For more information about increment instructions, reference 4.F. | |
| The format of increment instructions is: | |
| XXX R, V | |
| XXX is the three-letter instruction code (ex. "ADI" or "MUL"). | |
| R is a register with the value of R0, R1, R2, R3, R4, R5, R6, or R7. R | |
| designates the first operand of the math instruction, and is also the | |
| destination of the result of the math instruction. | |
| V is a value from 1 to 32. | |
| The immediate instructions are: | |
| ADI R = R + V Adds V to R. | |
| SBI R = R - V Subtracts V from R. | |
| NOTE: You can use "INC RX" as a subtitute for "ADI RX, 1", and "DEC RX" as a | |
| substitute for "SBI RX, 1". | |
| === 2.C. Bit-shifting Instructions ============================================ | |
| The YCPU can shift bits in a register left or right. For more information about | |
| bit-shifting instructions, reference 4.C. | |
| The format of Bit-shifting instructions is: | |
| XXX R, V | |
| XXX is the three-letter instruction code (ex. "ASL" or "ROL"). | |
| R is a register with the value of R0, R1, R2, R3, R4, R5, R6, or R7. R is | |
| the register that will be shifted. | |
| V is usually a value from 1-16, but can also be a register with the value | |
| of R0, R1, R2, R3, R4, R5, R6, or R7. For more information about using | |
| registers for bit-shifting instructions, reference 4.C. | |
| The bit-shifting instructions are: | |
| ASL Shifts all bits in R by V bits to the left. | |
| Leftmost bits are set to 0. | |
| ASR Shifts all bits in R by V bits to the right. | |
| Rightmost bits are set to original value of bit 15. | |
| LSL Shifts all bits in R by V bits to the left. | |
| Leftmost bits are set to 0. | |
| LSR Shifts all bits in R by V bits to the right. | |
| Rightmost bits are set to 0. | |
| RNL Rotates all bits in R by V bits to the left, not using carry bit. | |
| RNR Rotates all bits in R by V bits to the right, not using carry bit. | |
| ROL Rotates all bits in R by V bits to the left, through the carry bit. | |
| ROR Rotates all bits in R by V bits to the right, through the carry bit. | |
| NOTE: If you noticed that ASL and LSL are mathmatically equivalent, nice catch! | |
| This is indeed the case - the processor treats these two instructions | |
| identically. | |
| === 2.D. Bit-testing Instructions ============================================= | |
| The YCPU can test and effect single bits in a register. For more information | |
| about bit-testing instructions, reference 4.D. | |
| The format of Bit-testing instructions is: | |
| XXX R, V | |
| XXX is the three-letter instruction code (ex. "BTT" or "BTX"). | |
| R is a register with the value of R0, R1, R2, R3, R4, R5, R6, or R7. R is | |
| the register that will be tested. | |
| V is usually a value from 0-15, but can also be a register with the value | |
| of R0, R1, R2, R3, R4, R5, R6, or R7. when V is a value, it is the index | |
| of the bit that will be tested and maybe changed. When V is a register, | |
| the lower 4 bits of the register's value are used as the index. | |
| The bit-testing instructions are: | |
| BTT Tests a bit in R. If the bit is clear, zero flag is cleared. If the | |
| bit is set, zero flag is set. | |
| BTC Tests a bit in R, and clears it. Equivalent to BTT, plus the bit | |
| will be cleared after the instruction. | |
| BTS Tests a bit in R, and sets it. Equivalent to BTT, plus the bit will | |
| be set after the instruction. | |
| BTX Tests a bit in R, and changes it. Equivalent to BTT, plus the bit | |
| will be changed (if clear, it will be set after the instruction; if | |
| it was set, it will be cleared). | |
| === 2.E. Branch Instructions ================================================== | |
| The YCPU can use branch instructions to move around in the code based on the | |
| condition of the flags in the flag register (FL). These flags are set by | |
| instructions, often as a result of the CMP instruction. When the conditions of | |
| the flag register are true, the YCPU will move its program counter register by | |
| the specified number of 16-bit instructions. For more information about branch | |
| instructions, reference 4.E. | |
| The format of Branch instructions is: | |
| XXX V | |
| XXX is the three-letter instruction code (ex. "BCC" or "BUF"). | |
| V is a value from -128 to +127. This is the number of 16-bit words that | |
| the PC register will be changed by. | |
| The branch instructions are: | |
| BCC Branch on unsigned fewer than - if carry flag in FL is clear. | |
| BCS Branch on unsigned higher than or same - if carry flag in FL is set. | |
| BNE Branch on not equal - if zero flag in FL is clear. | |
| BEQ Branch on equal - if zero flag in FL is set. | |
| BPL Branch on signed fewer than - if negative flag in FL is clear. | |
| BMI Branch on signed higher than or same - if negative flag in FL set. | |
| BVC Branch on no overflow - if overflow flag in FL is clear. | |
| BVS Branch on overflow - if overflow flag in FL is set. | |
| BUG Branch on unsigned greater than - if zero flag and carry flag set. | |
| BSG Branch on signed greater than - if negative flag and carry flag set. | |
| BAW Branch always. | |
| === 2.F. Jump Instructions ===================================================== | |
| You use jump instructions to continue executing the program at a new address. | |
| The new address can be near or far (for more information about far jumps, | |
| reference 3.F.4.). For more information about these instructions, reference 4.G. | |
| The format of jump instructions is: | |
| XXX M | |
| XXX is the three-letter instruction code (ex. "JMP" or "JSR"). A jump or | |
| call can be to a near address or far address. The default address type | |
| is near. You can specify a far address by adding the text ".f" to | |
| the end of XXX (ex. "JMP.F"). | |
| M is the value that PC will be set to when this instruction is executed. | |
| Jump instructions use the same addressing modes as math instructions: | |
| Addressing Mode Syntax Value is... | |
| Immediate $1234 Value of Next Word | |
| Absolute [$1234] Mem[Next Word] | |
| Register RX Value of Register (R0 ... R7) | |
| Indirect [RX] Mem[R] | |
| Indirect Offset [RX,$1234] Mem[R + Next Word] | |
| Indirect Indexed [RX,RX] Mem[R+R] At least one register | |
| must be R4, R5, R6, or R7. | |
| The jump instructions are: | |
| JMP Unconditional jump to new address. | |
| JSR Unconditional jump to new address, saves return address to stack. | |
| === 2.G. Stack Instructions ==================================================== | |
| You use stack instructions to push registers to the stack, or pop registers to | |
| the stack. For more information about stack instructions, reference 4.H. | |
| The format of stack instructions is: | |
| XXX R[, R, R...] | |
| XXX is the three-letter instruction code (ex. "PSH" or "POP"). | |
| R is either one register or a list of registers separated by commas. | |
| The processor sequentially accesses the stack to push or pop each | |
| specified register in a specific order (see 4.H.). | |
| The stack Instructions are: | |
| POP Pop values from the Stack into registers. | |
| PSH Push values of registers onto the Stack. | |
| In addition, you may use the STX instruction to directly modify the stack with | |
| an immediate value. The format of the STX instruction is "STX V" where V is a | |
| value from -128 to 127. Following this instruction, the stack will be modified | |
| by the given number of 16-bit words relative to its previous value. | |
| === 2.H. Processor Functions =================================================== | |
| The processor has a number of instructions that activate special functions. | |
| These are described in brief here, more thoroughly in in section 4.I., and in | |
| great detail throughout Section 3. The processor function instructions are: | |
| CLF [N][,C][,Z][,V] Clears the specified bits in the FL register. Any | |
| combination of these flags is valid. | |
| Exs: CLF Z (or) CLF C, V, Z (or) CLF N, V | |
| HWQ V Sends a message of type V to the hardware bus. | |
| Reference 3.C. | |
| Ex. HWQ 1 (or) HWQ 128 | |
| LSG S Load segment register S from the stack. | |
| Ex. LSG CS | |
| RTI Return from interrupt handler. Reference 3.D.8. | |
| RTS Return from subroutine - pops a value from the stack | |
| and sets PC to that value. | |
| SEF Sets the specified bits in the FL register. Same | |
| parameter flags as CLF. | |
| SLP Halts the processor until it receives an interrupt. | |
| SSG S Save segment register S to the stack. | |
| Ex. SSG DS | |
| SWI Call software interrupt. Reference 3.D.3. | |
| ### 3. Hardware Information #################################################### | |
| The YCPU is a 16-bit processor designed to be powerful without being complex. A | |
| hobbyist can begin programming software knowing only the syntax of their | |
| assembler of choice and the way the RESET interrupt functions. Experts and | |
| developers of operating systems will enjoy the processor's many features and the | |
| easy transfer between supervisor, user, and interrupt modes. This section | |
| describes the processor's functions in detail. We begin with a description of | |
| the processor's memory model. | |
| --- 3.1. MEMORY MODEL ---------------------------------------------------------- | |
| The YCPU's eight data/address registers are each 16-bit. This means that all | |
| data handled by a single register can only address values between 0-65,536 when | |
| unsigned, or -32,768 to 32,767 when signed. The processor does have several | |
| instructions where two 16-bit operands combine to create a 32-bit results (for | |
| example, multiplication). When this occurs, the 'high' 16-bits of the result | |
| are stored in R0. The programmer has the choice to also store the low 16-bits | |
| of the result in R0, which would overwrite the high bits, or choose a different | |
| register for the destination of the low bits. | |
| With regards to addresses, the 16-bit limit means that all logical addresses | |
| can only address 64 kilobytes of memory at any time. However, using a memory | |
| management unit (MMU), the processor can access multiple 64 kilobyte areas of | |
| the processor at once. These areas are called 'segments'. For example, the | |
| processor might read code from one segment while copying data from a second | |
| segment to a third segment, while the stack pushed and pulled data from a fourth | |
| segment, and interrupts are handled by code in a fifth segment. | |
| Where segments are located in memory memory and how large they are is | |
| contolled by the processor's segment registers. There are nine of these: four | |
| describing the code, data, extra data, and stack segments for the processor's | |
| supervisor mode, an identical four for the processor's user mode, and one | |
| segment register that controls the segment used when the processor is handling | |
| an interrupt. | |
| --- 3.2. INSTRUCTION WIDTH: 16-BIT --------------------------------------------- | |
| For most instructions, the only addressable unit of memory is a 16-bit word. | |
| 8-bit instructions are supported for any instruction that uses the "ALU" bit | |
| pattern: Load, Store, Add, Subtract, Multiply, Divide, Bitwise And, Bitwise Or, | |
| Bitwise Not, Bitwise Exclusive Or, Compare, and Negate. When executing 8-bit | |
| instructions in registers, the upper 8-bits of memory are cleared and ignored. | |
| When executing an 8-bit STOre operation, the processor will store only one byte, | |
| and the second byte in the 16-bit word in memory will not be affected. When | |
| executing an 8-bit load operation, the processor will load only the lower byte | |
| at the address, and the upper 8-bits of the destination register will be | |
| cleared. | |
| For all other instructions there is no support for 8-bit maths. All other | |
| instructions operate on 16-bit vales at all times. | |
| --- 3.3. MEMORY ACCESS TO UNALIGNED ADDRESSES ---------------------------------- | |
| For 16-bit memory access, access is quickest when aligned to 2-byte boundaries, | |
| and slower when accesses are unaligned. Thus, memory accesses from $0000 and | |
| $0002 are faster than $0001 and $0003. For unaligned memory accesses, the YCPU | |
| loads the two bytes for a 16-bit word in separate memory access cycles. | |
| For 8-bit access, the YCPU loads only one 8-bit value. A single 8-bit load is | |
| as fast as an aligned 16-bit load, regardless of alignment. | |
| --- 3.4. REQUIRED HARDWARE ----------------------------------------------------- | |
| When the processor first powers on and each time it is RESET, it returns to a | |
| known state described in 3.G. The processor then executes instructions located | |
| in an on-board read only memory (ROM) chip. To access this chip, the processor | |
| relies on a hardware bus (YBUS). Thus, to execute any instructions the processor | |
| must be connected to a bus and a ROM chip. Of course, any useful work will | |
| likely require random access memory (RAM) as well, but RAM is not required power | |
| on the processor. Note that the amount of RAM and ROM available to the | |
| processor is not known to the processor. However, a programmer can query the | |
| amount of RAM/ROM with the instruction HWQ $03. For more information about this | |
| query operation, see 3.C.1. | |
| === 3.A. Registers ============================================================= | |
| The processor uses eight general purpose registers for most instructions. | |
| These registers are named R0, R1, R2, R3, R4, R5, R6, and R7. See 3.A.1. | |
| The processor has five control registers. These change the flow of the | |
| program. For more information, see 3.A.2. These are: | |
| FL: Flags register. | |
| PC: Program Counter. | |
| PS: Processor Status. | |
| SP: Stack Pointer. The YCPU has separate stack pointers for user mode (USP) | |
| and supervisor mode (SSP). | |
| The processor also has access to 9 32-bit segment registers. Note that you | |
| do not need to use these to write code, but they can be used for memory | |
| management. Four of the segment registers are used for the code, data, extra | |
| data, and stack segments accessed in Supervisor mode, and four for the | |
| segments accessed in User mode. In addition, there is one Interrupt segment | |
| register, the segment used during Interrupts. For more information, | |
| see 3.F. Memory Management. The segment registers are: | |
| CS: Code Segment. One for Supervisor (CSS), one for user mode (CSU). | |
| DS: Data segment. One for Supervisor (DSS), one for user mode (DSU). | |
| ES: Extra Data segment. One for Supervisor (ESS), one for user mode (ESU). | |
| SS: Stack segment. One for Supervisor (SSS), one for user mode (SSU). | |
| IS: Interrupt segment. Used in place of CS when bits I and M in PS are set. | |
| --- 3.A.1. GENERAL PURPOSE REGISTERS ------------------------------------------- | |
| The processor has 8 general purpose 16-bit registers. These registers are used | |
| as both data and address registers, are completely interchangeable (orthogonal), | |
| and are directly referenced and modified by most instructions. | |
| There are a few exceptions to general purpose register interchangeability. | |
| * R0 is the destination of the high 16-bits of the result of MUL (multiply) | |
| and MLI (signed multiply) instructions, which have 32-bit results. If R0 is | |
| also the src/dest register, then the high 16-bits are lost, and R0 will | |
| contain the low 16-bits after the instruction completes. | |
| * Only registers R4 - R7 can be used as index registers for indirect indexed | |
| memory addressing. Thus, when executing an instruction with this addressing | |
| mode, at least one of the registers that are combined to create the memory | |
| address must be R4, R5, R6, or R7: | |
| Allowed: LOD R1, [R0, R4] ; one register is R4-R7. Valid. | |
| Allowed: LOD R1, [R4, R5] ; both registers are R4-R7. Valid. | |
| Disallowed: LOD R1, [R0, R2] ; neither register is R4-R7. Not valid. | |
| --- 3.A.2. PROCESSOR CONTROL REGISTERS ----------------------------------------- | |
| The processor has five 16-bit processor control registers. Unlike the general | |
| purpose registers, these are not accessible by most instructions. The five | |
| processor control registers are FL, PC, PS, SSP, and USP. | |
| FL: The FLag register. This register contains flags that are set by ALU | |
| instructions. | |
| The flags are as follows: | |
| FEDC BA98 7654 3210 | |
| NZCV .... .... .... | |
| [N]egative, [Z]ero, [C]arry, o[V]erflow | |
| PC: The Program Counter. Contains the address of the next instruction to | |
| execute. It is incremented by 2 after executing an opcode that does | |
| not reference an immediate word value, by 4 after executing an opcode | |
| that does reference an immediate word value, or by 8 after executing an | |
| opcode that references three immediate word values. See 3.E.1. for more | |
| information about immediate values. | |
| PS: The Processor Status. Setting or clearing bits in this register enables | |
| and disables processor features and modes. The bits are as follows: | |
| FEDC BA98 7654 3210 | |
| SMHI QUVW .... .... | |
| [S] - [S]upervisor Mode enabled. | |
| [M] - [M]emory segmenting hardware enabled. | |
| [H] - [H]ardware Interrupts enabled. | |
| [I] - Processor handling [I]nterrupt, read code/immediate values | |
| from IS instead of CS. | |
| [Q] - HWI Re[Q]uest in process, blocks hardware interrupts. | |
| [U] - Fault in [U]ser mode. | |
| [V] - Segment Fault error bit 0. See 3.D.5. | |
| [W] - Segment Fault error bit 1. See 3.D.5. | |
| SP: The Stack Pointer is the address of the first full stack space. It is | |
| decremented before a stack value is pushed onto the stack, and is | |
| incremented after a stack value is popped from the stack. The stack | |
| grows downward from its initial address, and should be initialized to | |
| an address at (Stack Bottom + 1). Example: If SP is set to $0000, the | |
| first pushed value will be at $fffe, and the first pulled value will | |
| be read from $0000. | |
| The processor has two different stack pointers - the Supervisor Stack | |
| Pointer, or SSP, is used while the processor is in Supervisor mode, and | |
| the User Stack Pointer, or USP, is used while the processor is not in | |
| Supervisor mode. | |
| === 3.B. Supervisor/User Modes ================================================= | |
| Supervisor mode is enabled when the S bit in the PS register is set, which is | |
| true on processor boot and whenever an interrupt is called. When the S status | |
| bit is clear, the processor is in User mode. | |
| In Supervisor mode, the processor: | |
| * Can execute privileged opcodes. | |
| * Can set and clear all bits in the process status register. | |
| * Can read and write to all processor control registers. | |
| * Can directly access the hardware bus with the HWQ instruction. | |
| * Uses the Supervisor Stack Pointer (SSP) for stack instructions. | |
| * Uses the Supervisor segment registers. | |
| In User mode, the processor: | |
| * Raises an 'Unprivileged Opcode' interrupt on executing privileged opcodes. | |
| * Cannot set or clear any bits in the process status register. | |
| * Cannot write to PS, but can read from it. | |
| * Cannot directly access the hardware bus. | |
| * Uses the User Stack Pointer (USP) for stack instructions. | |
| * Uses the User segment registers. | |
| === 3.C. Hardware Devices ====================================================== | |
| The processor interfaces with hardware devices through a modular Hardware Bus. | |
| This Hardware Bus can host up to 15 Devices in addition to the processor. | |
| The processor communicates directly with devices executing a Hardware Query | |
| instruction (See 3.C.1.), and can also address memory segments exposed by a | |
| device (See 3.F.1.). Devices can request the processor's attention by raising a | |
| hardware interrupt (See 3.D.2.). | |
| Connected Hardware Devices may include input (keyboard, mouse, touch), output | |
| (segment, character, and bitmap based displays, printers, dials, readouts), | |
| storage (disk, hard drive), networking, additional memory, and interfaces for | |
| hardware not directly connected to the Hardware Bus. A programmer can use the | |
| HWQ $02 instruction to identify what Hardware Device is present in a given | |
| Hardware Slot (See 3.C.1). | |
| Device Slot 0 on the Hardware Bus refers to the YCPU itself. Software can | |
| retrieve information about the YCPU by using the Hardware Query instruction to | |
| query the Device in Slot 0. | |
| Note that Hardware Devices can independently access the YCPU's active memory, | |
| but only one device or the processor can access memory at once. Thus, while a | |
| device is reading or writing memory, the processor is stalled. | |
| --- 3.C.1. INTERACTING WITH HARDWARE ------------------------------------------- | |
| Software interacts with hardware using the HWQ (HardWare Query) instruction. | |
| This instruction includes one immediate 8-bit operation index. The possible | |
| indexes are (undefined operation indexes raise a 'UndefFault' interrupt): | |
| HWQ Index Description | |
| $00 Query number of devices connected | |
| $01 Query device attached to bus in slot R0 | |
| $02 Send message to hardware device | |
| $03 Get RAM/ROM amounts in R0-R3. | |
| $80 Get RTC time | |
| $82 Get RTC interrupt interval | |
| $83 Set RTC interval | |
| HWQ $00 --- Query number of devices connected | |
| Calling HWQ operation $00 will query the Bus for the number of connected | |
| devices. The YCPU will store this value in R0. | |
| HWQ $01 --- Query device attached to bus in slot R0 | |
| Software can determine what device is present in each of the 16 Bus Slots by | |
| calling HWQ operation $01 with the index of the Bus Slot to check in R0. If no | |
| device is present, R0 will be set to "ERR_NO_DEVICE" ($ffff). If a device is | |
| present, the registers of the YCPU will be set as follows: | |
| R0: Device Type | |
| R1: Manufacturer ID | |
| R2: Device ID | |
| R3: Device Flags | |
| HWQ $02 --- Send message to hardware device | |
| Software can send messages to a Bus Device by calling HWQ operation $02. This | |
| will send a two-word message, consisting of the words in R1 and R2, to the | |
| Hardware Device in Bus Slot R0. If there is no hardware device in this Bus Slot, | |
| there will be no effect. If there is an active Hardware Device in this Bus Slot, | |
| one of several results will occur: | |
| * If the device can instantly respond to the message, it will acknowledge the | |
| message by setting R0 to "MSG_ACK" ($0001). R1 and R2 may also be used as | |
| return parameters, if required by the device. | |
| * If the device requires time to respond to the message, it will acknowledge | |
| the message by setting R0 to "MSG_WAIT" ($0002). When the device is ready | |
| to respond to the message, it will raise a Hardware Interrupt. | |
| * If the device requires access to main memory, the processor will be halted | |
| while the device reads/writes to memory. Generally, the memory read will | |
| be based on the contents of R1 and R2. Software can send more than two | |
| parameters to a device by using R1 or R2 as a pointer to memory. When the | |
| device has completed its operation, it will set R0 to "MSG_ACK" ($0001). | |
| * If the device encounters an error while responding to the message, it will | |
| acknowledge the message by setting R0 to "MSG_ERROR" ($FFFF). R1 and R2 | |
| will remain unchanged. | |
| HWQ $03 --- Get RAM/ROM amounts in R0-R3. | |
| Software can query the YBUS for the total amount of attached RAM and ROM by | |
| calling HWQ operation $03. After this operation, the total amount of RAM will | |
| be set in R0 and R1, with the high 16-bits set in R1, and the total amount of | |
| ROM will be set in R2 and R3, with the high 16-bits set in R3. If no RAM | |
| exists, both R0 and R1 will be set to “NO_MEMORY” ($FFFF). If no rom exists, | |
| both R2 and R3 will be set to “NO MEMORY” ($FFFF). | |
| Indexes $80, $82, and $83 are described in 3.H.. | |
| === 3.D. Interrupts ============================================================ | |
| An interrupt is a signal that indicates that an event requires immediate | |
| attention. Interrupts can be triggered by a hardware device, by software using | |
| the SWI opcode, or when the processor encounters a fault state. Each type of | |
| interrupt is identified by an index from 0 to 15. | |
| When the processor receives an interrupt, it gets the address of the interrupt | |
| handler for the type of interrupt received from the 'interrupt vector table', | |
| a list of 16 16-bit values located at address $0000 in the Interrupt Segment. It | |
| the sets PC to this value, and begins executing the code at this address. | |
| --- 3.D.1. THE INTERRUPT VECTOR TABLE ------------------------------------------ | |
| There are 16 interrupts in the Interrupt Vector Table. The software interrupt | |
| is raised by the instruction SWI, and the Hardware Interrupt is raised by a | |
| hardware that asserts an interrupt request. All other interrupts are raised | |
| by the processor itself on specified error states. The 16 interrupts are: | |
| Idx Name Description | |
| $0 Reset Raised when the processor's RESET line is pulled high. | |
| The processor will follow the boot sequence (See 3.G.). | |
| $1 Clock Raised when the processor's Real Time Clock ticks. The tick | |
| rate can be set by writing to the RTC register. | |
| $2 DivZeroFault Raised when the processor executes a division or modulus | |
| opcode where the operand containing the denominator is zero. | |
| $3 DoubleFault Raised when the processor faults while attempting to access | |
| an interrupt handler (See 3.D.6.). | |
| $4 StackFault Raised when the processor executes a POP or PSH instruction | |
| that would access an address outside of the stack segment. | |
| $5 SegFault Raised when the processor attempts to read from or write to | |
| an address within a Segment that has been protected from | |
| these instructions. | |
| The V and W status bits in PS describe the error. | |
| The first 16-bit word on the Stack contains the memory | |
| address that the processor attempted to access. | |
| $6 UnprivFault Raised when the processor attempts to execute a privileged | |
| opcode while in User mode. | |
| $7 UndefFault Raised when the processor attempts to execute an UNDEFINED | |
| opcode. | |
| $8 RESERVED Not currently used, never raised. | |
| $9 RESERVED Not currently used, never raised. | |
| $A RESERVED Not currently used, never raised. | |
| $B RESERVED Not currently used, never raised. | |
| $C HWI A device on the Hardware Bus has requested an interrupt. | |
| The first 16-bit word on the Stack contains the bus index of | |
| the requesting device. | |
| $D BusRefresh Raised when the hardware on the bus has changed. Note that | |
| all hardware ids at this point may be invalidated. | |
| $E DebugQuery Raised when the processor's DEBUG line is pulled high. | |
| $F SWI Raised by the SWI opcode. | |
| --- 3.D.2. HARDWARE INTERRUPTS ------------------------------------------------- | |
| A device on the CPU's hardware bus may request the CPU's attention by asserting | |
| an interrupt request (IRQ). While the Q status bit in PS is clear and the H | |
| status bit in PS is set, the processor checks for IRQs before executing each | |
| opcode. If a hardware device is asserting an IRQ when the processor checks, the | |
| processor will push a 16-bit word containing the bus index of the first device | |
| on the bus that is asserting an IRQ onto the stack as part of the hardware | |
| interrupt. This bus index must be pulled from the stack before RTI is executed! | |
| Note that devices in lower index slots in the hardware bus always have | |
| priority over devices in higher index slots. | |
| --- 3.D.3. SOFTWARE INTERRUPTS ------------------------------------------------- | |
| An interrupt may also be triggered by the SWI opcode. In this case, the | |
| processor will raise the 'software interrupt' interrupt vector, and the code | |
| at that interrupt must determine what function has been requested, based on the | |
| contents of the registers. | |
| Unlike hardware interrupts, software interrupts will be acknowledged | |
| regardless of the status of the Q status bit | |
| The H status bit only applies to hardware interrupts, and thus software | |
| interrupts will be acknowledged by the CPU if the H status bit is clear. | |
| --- 3.D.4. FAULT INTERRUPTS ---------------------------------------------------- | |
| For interrupts caused by an error condition, the U status bit in PS will be set | |
| if the processor was in user mode when the fault occured, or clear if the | |
| processor was in supervisor mode when the fault occured. Also, a 16-bit error | |
| code will be pushed to the stack after PS and PC. This error code must be pulled | |
| from the stack before RTI is executed! | |
| The error code will be equal to the instruction word that caused the fault. | |
| Interrupts designated as 'Faults' are: | |
| - DivZeroFault ($02), | |
| - DoubleFault ($03), | |
| - StackFault ($04), | |
| - SegFault ($05), | |
| - UnPrivFault ($06), and | |
| - UnDefFault ($07). | |
| --- 3.D.5. SEGMENT FAULTS ------------------------------------------------------ | |
| When a segment fault is raised, the processor status bits V and W describe the | |
| operation that caused the segment fault: | |
| V W Segment Fault Type | |
| 0 0 Attempted access to segment that is not loaded. (P bit set) | |
| 0 1 Attempted write of write-protected memory. | |
| 1 0 Attempted access to address greater than the segment size. | |
| 1 1 UNDEFINED. | |
| Note that writes to ROM memory will fail silently unless the MMU is enabled and | |
| the write-protect bit is set, which will result in a segment fault with V = 0 | |
| and W = 1. | |
| --- 3.D.6. FAULTS WHILE LOADING AN INTERRUPT HANDLER --------------------------- | |
| It is possible that the processor may fault when attempting to load an interrupt | |
| handler. This could happen if the interrupt segment is not present, or if the | |
| interrupt vector address for a given interrupt is outside the size of the | |
| interrupt segment. When this occurs, the processor will raise a DoubleFault | |
| interrupt. | |
| Note that because the DoubleFault interrupt will only occur when the processor | |
| is already handling an interrupt, the U status bit in PC will always be clear, | |
| regardless of whether the processor was in user mode when the original interrupt | |
| occured. | |
| If the processor fails to load the DoubleFault interrupt handler, it will enter | |
| a "TripleFault" state and reset one clock cycle later. Note that "TripleFault" is | |
| not an interrupt that can be handled by the programmer. There is no function to | |
| recover from a TripleFault. | |
| --- 3.D.7. THE INTERRUPT SEQUENCE ---------------------------------------------- | |
| When an interrupt is raised, the processor halts the current executing process. | |
| It then executes the following sequence of operations: | |
| 1. Save the state of PS to a temporary register. | |
| 2. If this is Fault interrupt (See 3.D.4. for a list of fault interrupts): | |
| If processor is in User mode, set the U status bit. If the | |
| processor is in Supervisor mode, clear the U status bit. | |
| 3. Set the S and I status bits in PS. The processor is now in Supervisor | |
| mode, and will read all instructions and immediate values from the | |
| Interrupt Segment (IS), instead of the Code Segment (CS). | |
| 4. Push the saved PS to the Stack. | |
| 5. Push PC to the Stack. | |
| 6. If this is a hardware interrupt: | |
| a. The Q status bit will be set. This blocks other hardware interrupts | |
| from occurring while the current interrupt is being processed. | |
| b. A 16-bit word containing the index of the device that raised the | |
| interrupt is pushed to the Stack. | |
| 7. If this is a Segment Fault: | |
| The V and W status bits are set as appropriate (See 3.D.5.). | |
| 8. If this is Fault interrupt (See 3.D.4. for a list of fault interrupts): | |
| Push a 16-bit error code to the stack. The error code is equal to to the | |
| instruction word that caused the Fault. | |
| 8. Set PC to IS[$0000 + (InterruptIndex * 2)]. | |
| 9. Execution continues. | |
| --- 3.D.8. RETURNING FROM AN INTERRUPT ----------------------------------------- | |
| When an interrupt handler ends, it should call RTI, which restores the values of | |
| PS and PC from the stack. If an interrupt handler modifies a register or changes | |
| the segment registers, it should save the state of the registers before doing | |
| so, and restore the same before returning from the interrupt handler. | |
| The RTI instruction follows this sequence: | |
| 1. Pop PC and PS from the Stack, restoring the value they had prior to the | |
| interrupt. | |
| 2. Execution Continues. | |
| === 3.E. Addressing Modes ====================================================== | |
| Many instructions are register-only: they can take only data loaded in registers | |
| as their source. ALU (including LOD and STO) and JMP/JSR instructions can access | |
| memory using these six addressing modes: | |
| Addressing Mode Syntax Value is... | |
| Immediate $1234 Value of Next Word | |
| Absolute [$1234] Mem[Next Word] | |
| Register Rx Value of Register | |
| Indirect [Rx] Mem[R] | |
| Indirect Offset [Rx,$1234] Mem[R + Next Word] | |
| Indirect Indexed [Rx,Rx] Mem[R+R] At least one of these registers must be | |
| R4, R5, R6, or R7. | |
| --- 3.E.1. BIT WIDTH OF INSTRUCTIONS ------------------------------------------- | |
| ALU instructions are by default 16 bits wide. Thus, all LOD instructions take | |
| 16 bits from memory, and ADD instructions operate on all 16 bits of memory. | |
| There is an alternate 8-bit mode for ALU instructions (ADD, STO, LOD, etc.): | |
| LOD.8 [$8000] | |
| STO.8 [R4] | |
| These alternate instructions will operate on only the lower 8-bits of a | |
| register. 8-bit LOD instructions will load a single byte into memory from a | |
| register. The high 8 bits of the destination register will be cleared. 8-bit STO | |
| instructions will store the low 8 bits from the source register. If the | |
| destination of the instruction is memory, only a single byte is stored in | |
| memory. If the destination is another register, the lower 8 bits of memory are | |
| stored, and the high 8 bits of the destination register are cleared. | |
| --- 3.E.1. IMMEDIATE VALUES ARE READ FROM THE CODE SEGMENT --------------------- | |
| All immediate values are read from memory in the code segment (CS), and follow | |
| immediately after the opcode describing the instruction referencing the code | |
| segment. | |
| --- 3.E.2. REFERENCING THE DATA AND EXTENDED DATA SEGMENT ---------------------- | |
| Normally, any address references to memory (with Absolute, Indirect, Indirect | |
| Offset, or Indirect Indexed) will come from the address of memory within the | |
| data segment (DS). This is implicit to the indirect addressing modes, but can | |
| also be specified. Appropriate syntax for accessing the DS is: | |
| LOD R0, [r1] OR LOD R0, DS[r1] | |
| These addressing modes also allow references to the extra data segment (ES). | |
| This must be made explicit. The appropriate syntax for accessing ES is: | |
| LOD R0, ES[r1] | |
| === 3.F. Memory Management ===================================================== | |
| Because the processor has a 16-bit logical address space, it can only address | |
| $10000 (65,536) bytes of linear address space at a time. This limited address | |
| space is augmented by the processor's integrated memory management unit (MMU) | |
| that, when enabled, implements segmented memory and virtual address translation. | |
| --- 3.F.1. THE SEGMENT REGISTERS ----------------------------------------------- | |
| The processor's Memory Management Unit allows access to segmented memory. There | |
| are four segments available for access during normal program operation (the code | |
| segment (CS), data segment and extra data segment (DS and ES), and the stack | |
| segment (SS)), and a fifth segment (the Interrupt Segment (IS)) used as the code | |
| segment when the processor is in Interrupt mode ('I' bit set in PS) and the | |
| Memory Management Unit is enabled ('M' bit set in PS). | |
| Each segment register is 32 bits in size: | |
| $03 $02 $01 $00 | |
| FEDC BA98 7654 3210 FEDC BA98 7654 3210 | |
| DWPA ssss ssss bbbb bbbb bbbb bbbb bbbb | |
| D - Hardware device flag: | |
| 0: Accesses to this segment will come from main memory. | |
| 1: Accesses to this segment will come from the hardware device at | |
| the index equal to the upper four 'b' bits (0-15). Where these bits | |
| are 0000, the accesses will come from the computer's onboard ROM | |
| chip. | |
| W - Write protection flag: | |
| 0: Write instructions to this segment will succeed. | |
| 1: Write-protected. Writing to this segment will fail and cause a | |
| segment fault interrupt. | |
| P - Not present flag: | |
| If this bit is set, access to this segment will cause a segment fault. | |
| A - Accessed flag: | |
| This bit is set every time this segment is written to. | |
| s - These bits determine the size of the segment. This value is left shifted | |
| by 8 and incremented by 256 for a range of 256 - 2^16. | |
| b - When Hardware device flag bit 'D' is clear: | |
| These bits determine the base address of the memory that is mapped to | |
| this segment within virtual address space. The base address is left | |
| shifted by 8 for a range of 0 - 2^28-256. See 3.F.3. | |
| When Hardware device flag bit 'D' is set: | |
| The upper four 'b' bits indicate the device the segment is addressing | |
| (note that the YCPU's ROM is indicated by setting the high 'b' bits to | |
| device 0). The lower sixteen 'b' bits determine the base address of the | |
| memory that is mapped to the segment. This base address is left shifted | |
| by 8 for a range of 0 - 2^24-256. See 3.F.3. | |
| --- 3.F.2. ADDRESS TRANSLATION WHEN THE MMU IS DISABLED ------------------------ | |
| When the M status bit in PS is clear, the MMU is disabled and the segment | |
| registers are not used for memory access. Accesses to memory occur as if the | |
| segments were set to these values: | |
| CS: $8FF0 0000 ; CS in ROM, base = $00000000, size = $10000 | |
| DS: $0FF0 0000 ; DS in RAM, base = $00000000, size = $10000 | |
| ES: $0FF0 0000 ; ES in RAM, base = $00000000, size = $10000 | |
| SS: $0FF0 0000 ; SS in RAM, base = $00000000, size = $10000 | |
| IS: $8FF0 0000 ; IS in ROM, base = $00000000, size = $10000 | |
| --- 3.F.3. ADDRESS TRANSLATION WHEN THE MMU IS ENABLED ------------------------ | |
| When the M status bit in PS is set, the MMU is enabled, and will translate | |
| memory references to physical addresses using the contents of the segment | |
| registers. This is done by adding the segment base address to the address of | |
| the specified reference. The translation is as follows: | |
| If the 'D' bit is set, then the YCPU requests device memory space from the YBUS | |
| from the device with index equal to the upper 4-bits of the 'd' bits. If this | |
| index equals 0, then the memory access is to on-board read only memory. | |
| 1. The low 16-bit 'base address' portion of the segment register is | |
| shifted left by 8 (multiplied by 256). | |
| 2. The logical address of the instruction is added to the base address. | |
| 3. The combined value is the physical address. An example follows: | |
| Logical address $----1234 | |
| Segment device index $-D------ | |
| Segment base address $--8765-- | |
| Device 'D' address: $--877734 | |
| If the 'D' bit is clear, then the YCPU requests memory space from random | |
| access memory (RAM) on the YBUS. | |
| 1. The 20-bit 'base address' portion of the segment register is shifted | |
| left by 8 (multiplied by 256). | |
| 2. The logical address of the instruction is added to the base address. | |
| 3. The combined value is the physical address. | |
| Logical address $----1234 | |
| Segment base address $-98765-- | |
| Memory address: $-9877734 | |
| The segment used for a given memory address is implied by the opcode of the | |
| executing instruction. All instructions, operands and immediate values are | |
| taken from the Code Segment. All stack instructions (push, pop) are taken | |
| from the Stack Segment. All other instructions can use either the Data | |
| Segment or the Extra data Segment. | |
| Note that there are different Segment Registers for user and supervisor mode. | |
| The supervisor can set both sets of Segment Registers, while the user mode can | |
| set neither. | |
| --- 3.F.4. FAR JUMPS ----------------------------------------------------------- | |
| The YCPU is internally 16-bit, and each segment can only address only 16-bits of | |
| logical address space. This includes the executing instructions in the code | |
| segment. As noted infra, software may manipulate the segment registers using the | |
| LSG (Load Segment Register) and SSG (Store Segment Register). This will change | |
| the segments that are currently active in memory. | |
| Running software may also replace the code segment register in memory using a | |
| 'far jump'. Where a normal jump instruction sets only the PC register, a far | |
| jump will also write a new 32-bit value to the code segment register, which | |
| will now describe a new code segment containing the address the new PC value | |
| will reference. | |
| An example of a far jump with immediate addressing will help illustrate how this | |
| works. Note that 'immediate addressing' indicates that the processor uses the | |
| next word following the current instruction as the new value of the new PC. With | |
| a far jump, the processor will use two words immediately following the first | |
| operand as the second operand, least significant byte first, as follows: | |
| JMP.F $FF06, $83600008 | |
| The processor sees this instruction as 4 words (8 bytes) containing four | |
| sets of data: | |
| $07_____ $06_____ $05_____ $04_____ $03_____ $02_____ $01_____ $00_____ | |
| DWPAssss ssssbbbb bbbbbbbb bbbbbbbb aaaaaaaa aaaaaaaa OOOOOOOO OOOOOOOO | |
| O = 16-bit opcode, indicating a 'far jump immediate' instruction. | |
| a = the address of the PC within the new segment. | |
| b = the base address of the new segment | |
| s = the size of the new segment. | |
| DWPA = protection bits of the new segment. | |
| Following the operation, the PC will be set to $FF06, and CS will be set to | |
| $80000008, indicating that the code segment points to ROM ('D'evice bit set, | |
| upper 'b' bits equal zero) with the base of the segment at $00000800, and the | |
| size of the segment equal to $03600. | |
| Note 1: Far jumps are only accessible from Supervisor mode. If the processor | |
| attempts to execute a far jump while in user mode, the processor will | |
| raise the 'UnPrivFault' interrupt. Thus, these instructions could still | |
| be used while in User mode; the processor interrupt would be used to | |
| 'trap' these instructions. Alternatively, software running in User mode | |
| could use a SWI instruction for the same purpose, if the Supervisor mode | |
| program was designed to interpret this function. | |
| Note 2: When the MMU is disabled, a far jump will still set the code segment | |
| register, but because the MMU is disabled, this will not effect the | |
| segment of the current executing code. | |
| --- 3.F.5. ACCESSES TO MEMORY -------------------------------------------------- | |
| Any memory accesses to segments that are not loaded ('P' bit in segment register | |
| set) or outside of a segment's defined space (ex. read to address $c000 when | |
| segment size is $8000), will result in a segment fault. | |
| Any memory accesses to addresses that are not connected to real memory will | |
| result in a return of all bits clear: '$0000'). | |
| === 3.G. Boot/Reset Sequence =================================================== | |
| At initial power on, the state of all memory, registers, and cache is unknown. | |
| The processor raises the RESET interrupt at power on, placing the processor | |
| in the following known state: | |
| RTC Tick <- Disabled ; RTC will not raise interrupts. | |
| PS <- $8000 ; Supervisor mode is enabled, all other | |
| ; processor features are disabled. | |
| ; Because the MMU is disabled, memory | |
| ; accesses will be translated as per 3.F.2. | |
| PC <- [InterruptTable[$0]] ; Execute 'RESET' interrupt code. | |
| === 3.H. The Real Time Clock =================================================== | |
| The processor contains an integrated Real Time Clock (RTC). The RTC maintains | |
| and updates its internal time data indefinitely, even when the processor is | |
| powered down. The processor can query the RTC for the current time. | |
| --- 3.H.1. RTC Date/Time data -------------------------------------------------- | |
| The clock provides time data with the following precision: | |
| Year: 8 bits (0-255) | |
| Month: 4 bits (0-11) | |
| Day: 5 bits (0-31) | |
| Hour: 5 bits (0-23) | |
| Minute: 6 bits (0-59) | |
| Second: 6 bits (0-59) | |
| M.Sec.: 12 bits (0-999) | |
| This data is loaded to R0-R3 upon calling HWQ $80, in this format: | |
| FEDC BA98 7654 3210 | |
| R0: 8 bits Year, 4 bits Month YYYY YYYY .... MMMM | |
| R1: 5 bits Day, 5 bits Hour ...D DDDD ...h hhhh | |
| R2: 6 bits Min, 6 bits Second ..mm mmmm ..ss ssss | |
| R3: 16 bits Tick tttt tttt tttt tttt | |
| The original epoch for this device is 1 January 1900 at Midnight. This device | |
| will 'roll over' at 1 January 2156. YpsilonTech offers technical assistance at | |
| exceptionally reasonable rates to companies who wish their software to | |
| gracefully handle this roll-over. YpsilonTech accepts no responsibility for | |
| software written without this assistance, and thus experience a "Y2156" bug. | |
| --- 3.H.2. The CLOCK interrupt ------------------------------------------------- | |
| The RTC also provides a CLOCK interrupt that can be enabled or disabled. The | |
| frequency of this interrupt, in hertz (times per second) can also be specified. | |
| For example, an interval value of 1 would raise the CLOCK interrupt once per | |
| second. An interval value of 100 would raise the CLOCK interrupt 100 times | |
| per second. | |
| A programmer may query the current interrupt interval with HWQ $82. After this | |
| instruction, R0 will be set to the actual CLOCK interrupt rate. | |
| The processor can set the desired interrupt interval with HWQ $83, with a value | |
| indicating the desired interrupt frequency in R0. If R0 is $0000, the interrupt | |
| will be disabled. Otherwise, the CLOCK interrupt will be raised at a frequency | |
| of R0 hertz, capped to a maximum of cpu frequency divided by 1024. | |
| After this operation, R0 will be set to the actual CLOCK interrupt frequency. | |
| Software can thus request a high CLOCK rate, and be informed of the actual CLOCK | |
| rate by examining R0. | |
| === 3.I. Switching Context ===================================================== | |
| The RTI instruction can also be used to switch the processor into user mode, | |
| even switching contexts entirely when doing so. | |
| --- 3.I.1. Switching from Supervisor Context to User Context ------------------- | |
| When the MMU is enabled, the layout of memory is different in Supervisor and | |
| User modes. Thus, as long as the MMU's User mode memory has been set ahead of | |
| time, the RTI instruction can be used to switch the context of a running | |
| program. | |
| To change context from supervisor to user mode, the MMU's user mode segment | |
| registers should be set, and the stack should be loaded with user-mode values | |
| for R0-R7, FL, USP, PS, and PC registers. The PS register value in the stack | |
| should be set with the S status bit clear (for user mode), and the M status | |
| bit set (for MMU active). Then, to switch to the user context: | |
| 1. Load the segment registers with the necessary user data (in this | |
| example, these stacks are stored as 8 16-bits words on the stack). | |
| 2. Pop R0-R7 from the stack. | |
| 3. Pop FL, USP. | |
| 4. Use RTI to pop PS, PC from the stack (PS should have S bit cleared). | |
| 5. Execution will continue in the User mode context. | |
| LSG USS | |
| LSG UES | |
| LSG UDS | |
| LSG UCS | |
| POP R0, R1, R2, R3, R4, R5, R6, R7 | |
| POP FL, USP | |
| RTI ; pops PS and PC | |
| To save the same context (when responding to an interrupt from user mode): | |
| Note that upon entering the interrupt, the stack looks like this: | |
| [ ... ] | |
| [ PS ] | |
| SP --> [ PC ] | |
| 1. Push FL and USP to the stack. | |
| 2. Push R0-R7 to the stack. | |
| 3. Save the user segment registers to the stack. | |
| PSH FL, USP | |
| PSH R0, R1, R2, R3, R4, R5, R6, R7 | |
| SSG UCS | |
| SSG UDS | |
| SSG UES | |
| SSG USS | |
| As an interesting aside, this context is only 40 bytes. | |
| --- 3.I.2. Switching Context while in Supervisor Mode -------------------------- | |
| Switching context from supervisor to supervisor is more difficult, as modifying | |
| the active segment registers will change the instruction that PC is operating | |
| on. It is advised that the software either disable the MMU as part of this | |
| operation, or lay out the banks of memory in such a way that when changing | |
| banks, the context changing sequence will go on interrupted (the same sequence | |
| of context changing might be used in all banks). | |
| ### 4. Instruction Set Description ############################################# | |
| The YCPU's instruction set is comprised of 58 unique instructions (although an | |
| assembler may define other instructions as 'macros' - for example, a one-cycle | |
| NOP instruction could be defined as 'LOD R0, R0'). | |
| All instructions are comprised of single 16-bit program words. Some instructions | |
| may be suffixed by a single 16-bit immediate value. One instruction - the far | |
| jump immediate instruction - is suffixed by three 16-bit immediate values. | |
| All instructions are defined by the 8-bit low octet of the 16-bit program word. | |
| Attempted execution of a program word that does not have a defined 8-bit low | |
| octet will raise the 'undefined' interrupt. | |
| LOW OCTET Mnemonic Priv? Bit Pattern Description Cycles | |
| 0000 0... CMP ALU Compare R and M, sets FL 1 | |
| 0000 1... NEG ALU R = 0 - M (two's complement) 1 | |
| 0001 0... ADD ALU R = R + M 1 | |
| 0001 1... SUB ALU R = R - M 1 | |
| 0010 0... ADC ALU R = R + M + C 1 | |
| 0010 1... SBC ALU R = R - M - (1 - C) 1 | |
| 0011 0... MUL ALU R = R * M (16x16=32b) 8 | |
| 0011 1... DIV ALU R = R / M 48 | |
| 0100 0... MLI ALU R = R * M (signed 16x16=32b) 8 | |
| 0100 1... DVI ALU R = R / M (signed) 48 | |
| 0101 0... MOD ALU R = R % M (modulus) 48 | |
| 0101 1... MDI ALU R = R % M (modulus, signed) 48 | |
| 0110 0... AND ALU Bitwise and 1 | |
| 0110 1... ORR ALU Bitwise or 1 | |
| 0111 0... EOR ALU Bitwise exclusive or 1 | |
| 0111 1... NOT ALU Bitwise not 1 | |
| 1000 0... LOD ALU Load 1 | |
| 1000 1... STO ALU Store 1 | |
| 1001 0... Bxx BRA Branch instructions 1 | |
| 1001 1... Bxx BRA Branch instructions 1 | |
| 1010 0000 ASL SHF Arithmetic Shift left 4 | |
| 1010 0001 LSL SHF Logical Shift Left 4 | |
| 1010 0010 ROL SHF Rotate Through-Carry Left 2 | |
| 1010 0011 RNL SHF Rotate No-Carry Left 2 | |
| 1010 0100 ASR SHF Arithmetic Shift Right 4 | |
| 1010 0101 LSR SHF Logical Shift Right 4 | |
| 1010 0110 ROR SHF Rotate Through-Carry Right 2 | |
| 1010 0111 RNR SHF Rotate No-Carry Right 2 | |
| 1010 1000 BTT BTI Test a bit 2 | |
| 1010 1001 BTX BTI Test a bit and change it 2 | |
| 1010 1010 BTC BTI Test a bit and clear it 2 | |
| 1010 1011 BTS BTI Test a bit and set it 2 | |
| 1010 110. SET SEI Set register to value 1 | |
| 1010 1110 SEF FLG Set flag bit 1 | |
| 1010 1111 CLF FLG Clear flag bit 1 | |
| 1011 000. PSH STK Push to stack 1 | |
| 1011 001. POP STK Pop from stack 1 | |
| 1011 0100 xxx / PRX Processor functions * | |
| 1011 0101 LSG/SSG X MMU Load / Save Segment Register 4 | |
| 1011 0110 ADI IMM Increment by value 1 | |
| 1011 0111 SBI IMM Decrement by value 1 | |
| 1011 1000 JMP / JMI Jump 2 | |
| 1011 1001 JSR / JMI Jump to Subroutine 4 | |
| 1011 1010 HWQ X HWI Hardware Bus Query 4 | |
| 1011 1011 STX X STX Stack Immediate 1 | |
| 1011 11.. --- --- UNDEFINED (4 opcodes) - | |
| 11.. .... --- --- UNDEFINED (64 opcodes) - | |
| === 4.A. Bit Patterns ========================================================== | |
| ALU Bit Pattern | |
| FEDC BA98 7654 3210 | |
| sAAA rrrE OOOO ORRR | |
| R = Destination/Source Register | |
| O = Opcode | |
| A = Addressing Mode | |
| r = Second Operand Register. | |
| E = 8-bit Mode. See Note 1, below. | |
| s = Extra Data Segment select. See Note 2, below. | |
| i = Index Register. See Note 3, below. | |
| p = processor control register index. See Note 4, below. | |
| sAAA rrre OOOO ORRR Addressing Mode Example Syntax Cycles | |
| .000 000e Immediate LOD R0, $1234 +1m | |
| s000 001e Absolute LOD R0, [$1234] +2m | |
| .000 1ppp Control register LOD R0, PS | |
| .001 rrre Register LOD R0, r1 | |
| s010 rrre Indirect LOD R0, [r1] +1m | |
| s011 rrre Indirect Offset LOD R0, [r1,$1234] +2m | |
| s1ii rrre Indirect Indexed LOD R0, [r1,i2] +1m | |
| Note 1: When the 'e' bit is set, the ALU processes values in its 8-bit | |
| mode. To use 8-bit mode for ALU instructions, follow the normal | |
| opcode with a ".8" flag. Examples follow: | |
| Instruction Compiled as: | |
| LOD.8 R0, $34 LOD R0 = $34, 8-bit operation. Hi-8 bits | |
| of immediate value are ignored. | |
| LOD.8 R0, $1234 LOD R0 = $34, 8-bit operation. Hi-8 bits | |
| of immediate value are ignored. | |
| STO.8 R0, [R1,R4] STO R0 = [R1,R4], 8-bit operation. | |
| The ALU operating in 8-bit mode has the following modified behavior: | |
| 1. Only the low 8-bits of the input registers are used. | |
| 2. Only the low 8-bits of the output register are set. The high | |
| 8-bits of the output register are cleared (set to '0'). | |
| 3. The [N]egative flag bit is set if bit 7 is set (with 16-bit | |
| instructions, the N flag is set if bit 15 is set). | |
| 4. Only the low 8 bits of an immediate value are loaded, and the | |
| following byte is skipped (the entire 16 bits of offsets and | |
| absolute values are still used). | |
| Note 2: When the 's' bit is clear, all accesses to memory are within the | |
| Data Segment (DS). When 's' is set all access are within the | |
| Extra Data Segment (ES). Reference 3.E.2. | |
| Note 3: There are two index register bits, which together indicate | |
| register R4-R7. Therefore, at least one register in indirect | |
| indexed addressing must be R4-R7; the other can be any of R0-R7. | |
| The index register bits select a register as follows: | |
| ii Register | |
| 00 R4 | |
| 01 R5 | |
| 10 R6 | |
| 11 R7 | |
| Note 4: The control register operand indexes are as follows: | |
| Index Desc. User write? | |
| $00 FL register Y | |
| $01 PC register Y | |
| $02 PS register N | |
| $03 RESERVED, UNDEFINED. N | |
| $04 RESERVED, UNDEFINED. N | |
| $05 RESERVED, UNDEFINED. N | |
| $06 USP Y | |
| $07 current Stack Pointer (USP / SSP) Y | |
| It is always possible to read control registers to general | |
| purpose registers, regardless of supervisor/user mode. However, | |
| user mode is limited in which processors it can write to. | |
| Note 5: The instruction LOD R0, R0 will cause the processor to do | |
| nothing for one cycle - it is equivalent to NOP. All other | |
| LOD instructions that have the same register for source and | |
| destination have the same result. | |
| BRA Bit Pattern | |
| FEDC BA98 7654 3210 | |
| bbbb bbbb OOOO Occc | |
| O = opcode | |
| b = signed 8-bit offset (multiplied by 2) | |
| c = condition (See 4.E. 'Branch Instructions') | |
| BTI Bit Pattern | |
| FEDC BA98 7654 3210 | |
| rrrR ssss OOOO OOOO | |
| O = Opcode | |
| r = register to test | |
| R = 0: test bit with index in immediate value 's' ($0 - $f) | |
| 1: test bit with index in lower four bits of register 'Rs'. | |
| 'Rs' register is R0-R7, picked by lower three bits of 's' value. (s & $07) | |
| index of bit to check = (Rs & $000F). | |
| FLG Bit Pattern | |
| FEDC BA98 7654 3210 | |
| NZCV .... OOOO OOOO | |
| O = Opcode | |
| N = Negative flag bit | |
| Z = Zero flag bit | |
| C = Carry flag bit | |
| V = oVerflow flag bit | |
| HWI Bit Pattern | |
| FEDC BA98 7654 3210 | |
| iiii iiii OOOO OOOO | |
| O = Opcode | |
| i = Type of Hardware Busy Query operation. See 3.C.1. for a list of | |
| valid operation indexes. | |
| IMM Bit Pattern | |
| FEDC BA98 7654 3210 | |
| RRRv vvvv OOOO OOOO | |
| O = Opcode | |
| r = register to be incremented | |
| v = value to increment register by (5-bit value + 1, range of $01-$20) | |
| JMI Bit Pattern | |
| FEDC BA98 7654 3210 | |
| sAAA rrrF OOOO OOOO | |
| O = Opcode | |
| A = Addressing Mode | |
| r = Operand Register. | |
| F = Far Mode. See Note 1. | |
| s = Extra Data Segment select. See ALU Bit Pattern Note 2. | |
| i = Index Register. See ALU Bit Pattern Note 3. | |
| sAAA rrrF OOOO OOOO Addressing Mode Example Syntax Cycles | |
| .000 000F Immediate LOD R0, $1234 +1m | |
| s000 001F Absolute LOD R0, [$1234] +2m | |
| .001 rrr. Register LOD R0, r1 | |
| s010 rrrF Indirect LOD R0, [r1] +1m | |
| s011 rrrF Indirect Offset LOD R0, [r1,$1234] +2m | |
| s1ii rrrF Indirect Indexed LOD R0, [r1,i2] +1m | |
| Note 1: When the 'F' bit is clear, the jump is 'near', and the PC will | |
| be set to the value implied by the addressing mode, within the | |
| currently loaded 16-bit logical memory space. | |
| When the 'F' bit is set, the jump is 'far', and will not only | |
| change the PC, but will also change the logical memory space | |
| within the bank of the upper address. This process is detailed | |
| in 3.F.4. | |
| Far jumps are only available in Supervisor mode. | |
| Far jumps cannot use Register addressing. | |
| Addressing Mode 32-bit Segment: 16-bit Address: | |
| Immediate PC + 4 PC + 2 | |
| Absolute [(PC + 2) + 2] [PC + 2] | |
| Indirect [R + 2] [R] | |
| Indirect Offset [(R,$1234) + 2] [R,$1234] | |
| Indirect Indexed [R,i + 2] [R,i] | |
| Note 2: Far jumps triple the cycles taken to execute the instruction: | |
| Instruction Cycles | |
| JMP A 2 | |
| JMP.F A 6 | |
| JSR A 4 | |
| JSR.F A 12 | |
| JMP $1234 2+1m | |
| JSR $1234 4+1m | |
| JMP.F $1234, $12345678 6+3m | |
| JSR.F $1234, $12345678 12+3m | |
| MMU Bit Pattern | |
| FEDC BA98 7654 3210 | |
| u... rrro OOOO OOOO | |
| O = Opcode | |
| o = MMU operation: | |
| $0 = LSG: Pull one segment register from stack (4 bytes, 2 words). | |
| $1 = SSG: Push one segment register to stack (4 bytes, 2 words). | |
| Single segment register can be cs,ds,es,ss,csu,dsu,esu,ssu,is. | |
| r = segment register: | |
| $0 = cs (u = 0: css, u = 1: csu) | |
| $1 = ds (u = 0: dss, u = 1: dsu) | |
| $2 = es (u = 0: ess, u = 1: esu) | |
| $3 = ss (u = 0: sss, u = 1: ssu) | |
| $4 = is (u must be 0, raises UnDefFault interrupt otherwise). | |
| $5-$7 = undefined, raises UnDefFault interrupt. | |
| PRX Bit Pattern | |
| FEDC BA98 7654 3210 | |
| iiii iiii OOOO OOOO | |
| O = Opcode | |
| i = processor function index: | |
| $00 = RTS Return from subroutine. | |
| $01 = RTS.F Return from subroutine, far. | |
| $02 = RTI Return from interrupt. | |
| $03 = SWI Raise SoftWare Interrupt. | |
| $04 = SLP Sleep until Interrupt. | |
| SEI Bit Pattern | |
| FEDC BA98 7654 3210 | |
| RRRv vvvv OOOO OOOA | |
| O = Opcode | |
| R = destination register | |
| v = value | |
| A = alternate value select | |
| If A == 0: R = v Constant values from $00 - $1F | |
| If A == 1: | |
| v = $00...$0A : R = (2^(5+v)) Power of two constants 2^5 ~ 2^15. | |
| v = $0B...$1F : R = ($FFE0 + v). | |
| SHF Bit Pattern | |
| FEDC BA98 7654 3210 | |
| rrrR ssss OOOO ODoo | |
| O = Opcode | |
| o = Sub-Opcode | |
| 00 = ASx, 01 = LSx, 10 = ROx, 11 = RNx | |
| D = direction | |
| 0 = L, 1 = R | |
| r = register to shift | |
| R = shift value select, see s | |
| s = if R = 0, bits to shift (1-16) | |
| if R = 1, register to use as shift value (register index = .sss) | |
| STX Bit Pattern | |
| FEDC BA98 7654 3210 | |
| iiii iiii OOOO OOOO | |
| O = Opcode | |
| i = signed 8-bit offset, -128~+127 (multiplied by 2) | |
| STK Bit Pattern < 1 / 2 > | |
| FEDC BA98 7654 3210 | |
| rrrr rrrr OOOO OOO0 | |
| O = Opcode | |
| r = push/pop general purpose registers with indexes = (bit number - 8) | |
| STK Bit Pattern < 2 / 2 > | |
| FEDC BA98 7654 3210 | |
| su.. .pcf OOOO OOO1 | |
| O = Opcode | |
| f = push/pop FL register | |
| c = push/pop PC register | |
| p = push/pop PS register | |
| u = push/pop USP | |
| s = push/pop current Stack Pointer (USP / SSP) | |
| === 4.B. ALU Instructions ====================================================== | |
| Note: all ALU instructions support the .8 bitflag. | |
| ADC Add value to register with carry | |
| Operation: Rx + M + C -> Rx, C | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| ADD Add value to register, carry is ignored. | |
| Operation: Rx + M -> Rx, C | |
| For small immediate values, ($01-$20), ADD should be optimized to ADI. | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| AND Bitwise AND register with value | |
| Operation: Rx & M -> M | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| CMP Compares register with value and sets appropriate flags | |
| Operation: Z,C,N,V = Rx - M | |
| N [Negative] Set if Rx >= M (signed) | |
| Z [Zero] Set if Rx == M. | |
| C [Carry] Set if Rx >= M (unsigned) | |
| V [Overflow] Not affected. | |
| DIV Unsigned Divide register by value | |
| Operation: Rx / M -> Rx | |
| If divide by 0 is attempted, DivZeroFault interrupt is raised, Rx is unchanged. | |
| N [Negative] Always cleared. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| DVI Signed divide of register by value | |
| Operation: Rx / M -> Rx | |
| If divide by 0 is attempted, DivZeroFault interrupt is raised, Rx is unchanged. | |
| N [Negative] Set if bit 15 of Rx is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Set if $8000 / $FFFF is attempted, Rx = $8000 | |
| EOR Bitwise Exclusive OR of register with value | |
| Operation: Rx ^ M -> Rx | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| LOD Loads a value into a specified register | |
| Operation: M -> Rx | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| MDI Signed modulus of register by value. | |
| Operation: Rx % M -> Rx | |
| Sign of the result is the same as the sign of the dividend. | |
| If divide by 0 is attempted, DivZeroFault interrupt is raised, Rx is unchanged. | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| MLI Signed 16b register X 16b value with 32b result. | |
| Operation: Rx * M -> Rx,R0 | |
| R0 is set to the high 16-bits of the result before Rx is set with the low | |
| 16-bits of the result. If Rx and R0 are the same, R0 will equal the low | |
| 16-bits of the result, and the high 16-bits will be lost. | |
| N [Negative] Set if bit 15 of the high 16-bits is set. | |
| Z [Zero] Set if both the high 16-bits and Rx == 0. | |
| C [Carry] Set if high 16-bits != 0. | |
| V [Overflow] Not affected. | |
| MOD Modulus of register by value. | |
| Operation: Rx % M -> Rx | |
| If divide by 0 is attempted, DivZeroFault interrupt is raised, Rx is unchanged. | |
| N [Negative] Set if bit 15 of Rx is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| MUL Unsigned 16b register X 16b value with 32b result. | |
| Operation: Rx * M -> Rx,R0 | |
| R0 is set to the high 16-bits of the result before Rx is set with the low | |
| 16-bits of the result. If Rx and R0 are the same, R0 will equal the low | |
| 16-bits of the result, and the high 16-bits will be lost. | |
| N [Negative] Always cleared. | |
| Z [Zero] Set if the high 16-bits and Rx == 0. | |
| C [Carry] Set if high 16-bits != 0. | |
| V [Overflow] Not affected. | |
| NEG Changes the sign of a value, stores result in Source Reg. | |
| Operation: NEG(M) -> Rx | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] In 16-bit mode, set if input value is $8000, and Rx = $8000. | |
| In 8-bit mode, set if input is $..80, and Rx = $0080. | |
| Note 1: The result of NEG Rx where Rx = $8000 = $8000 | |
| Note 2: NEG.8 treats the input value as a 8-bit value. | |
| This ignores the high 8 bits of the input value. | |
| The result of NEG.8 clears the high 8 bits of the input value. | |
| NOT Bitwise NOT of value, stores result in Source Reg. | |
| Operation: !M -> Rx | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| ORR Bitwise OR of register with value. | |
| Operation: Rx | M -> Rx | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| SBC Subtract value from register, with carry. | |
| Operation: Rx - M - (1-C) -> Rx, C | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| STO Stores the value of a register into memory | |
| Operation: Rx -> M | |
| NOTE: Immediate and Register addressing is not available with STO opcodes. | |
| Thus the two opcodes that would code for STO with these addressing | |
| modes are UNDEFINED and will raise the raise the 'undefined' interrupt | |
| on execution. | |
| N [Negative] Not affected. | |
| Z [Zero] Not affected. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| SUB Subtract value from register, ignoring carry. | |
| Operation: Rx - M -> Rx, C | |
| NOTE: For small immediate values, ($01-$20), SUB should be replaced with SBI. | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| === 4.C. Bit Shifting Instructions ============================================= | |
| All bit-shifting instructions must specify the number of bits to be shifted. The | |
| number can be specified as an immediate constant from 1-16, or taken from a | |
| register. When specified as a constant, the number is the number of bit | |
| positions to shift. When specified as a register: | |
| 1. If the register value is equal to zero, no shift occurs. Flags are still | |
| affected. | |
| 2. If the register value is between 1 and 15, a shift occurs with that | |
| number of bits. | |
| 3. If the register value is greater than 15, a shift of | |
| (register value & $000F) bits occurs. | |
| ASL Arithmetic Shift Left | |
| Shifts all the bits of Rx X bits to the left. The leftmost X bits are set to 0. | |
| The carry flag is set if any bits shifted out were 1, otherwise clear. The | |
| result is that Rx is multiplied by 2^X, treating Rx as an unsigned word, and | |
| setting the carry flag if the result does not fit in 16 bits. | |
| Syntax: | |
| ASL R0, 8 ; Arithmetic Shift Left of R0 by 8 bits. | |
| ASL R0, R1 ; Arithmetic Shift Left of R0 by (R1 & $000F) bits. | |
| Operation: | |
| N [Negative] Set if bit 15 of the result is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if any bits shifted out were 1, otherwise clear. | |
| Clear on shift zero. | |
| V [Overflow] Not affected. | |
| ASR Arithmetic Shift Right | |
| Shifts all the bits of Rx X bits to the right. The rightmost X bits are copied | |
| from the old bit 15. The carry flag is set if any bits shifted out were 1, | |
| otherwise clear. The result is that Rx is divided by 2^X, treating Rx as a | |
| signed word, and setting the carry flag if the result does not fit in 16 bits. | |
| For positive values, this operation will divide towards 0; for negative values, | |
| this operation will divide towards -1. | |
| Operation: | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if any bits shifted out were 1, otherwise clear. | |
| Clear on shift zero. | |
| V [Overflow] Set if input != $FFFF (-1), and output == $FFFF. | |
| LSL Logical Shift Left | |
| This operation is equivalent to ASL. | |
| Operation: | |
| N [Negative] Set if bit 15 of the result is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if any bits shifted out were 1, otherwise clear. | |
| Clear on shift zero. | |
| V [Overflow] Not affected. | |
| LSR Logical Shift Right | |
| Shifts all the bits of Rx X bits to the right. The rightmost X bits are set to | |
| zero. The carry flag is set if any bits shifted out were 1, otherwise clear. The | |
| result is that Rx is divided by 2^X, treating Rx as an unsigned word, and | |
| setting the carry flag if the result does not fit in 16 bits. | |
| Operation: | |
| N [Negative] Set if bit 15 of the result is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if any bits shifted out were 1, otherwise clear. | |
| Clear on shift zero. | |
| V [Overflow] Not affected. | |
| RNL Rotate No-Carry Left | |
| Rotate all of the bits in Rx X bits to the left, without using the carry bit. | |
| Operation: | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| RNR Rotate No-Carry Right | |
| Rotate all of the bits in Rx X bits to the right, without using the carry bit. | |
| Operation: | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| ROL Rotate Through-Carry Left | |
| Rotate all of the bits in Rx X bits to the left, through carry. | |
| Operation: | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set to the contents of the old bit (16-X). | |
| Not affected on shift of zero. | |
| V [Overflow] Not affected. | |
| ROR Rotate Through-Carry Right | |
| Rotate all of the bits in Rx X bits to the right, through carry. | |
| Operation: | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set to the contents of the old bit (X-1). | |
| Not affected on shift of zero. | |
| V [Overflow] Not affected. | |
| === 4.D. Bit Testing Instructions ============================================== | |
| BTT Test a bit | |
| Operation: Rx{B} -> Z | |
| N [Negative] Not affected. | |
| Z [Zero] Set if Rx{B} is clear, clear otherwise. | |
| C [Carry] Not affected. | |
| V [Overflow] Not affected. | |
| BTX Test a bit and change it | |
| Operation: !Rx{B} -> Rx{B}, Z, C | |
| N [Negative] Not affected. | |
| Z [Zero] Set if old Rx{B} was clear, clear otherwise. | |
| C [Carry] Set if new Rx{B} is set. | |
| V [Overflow] Not affected. | |
| BTC Test a bit and clear it | |
| Operation: Rx{B} -> Rx{B}, Z, C | |
| N [Negative] Not affected. | |
| Z [Zero] Set if old Rx{B} was clear, clear otherwise. | |
| C [Carry] Set if old Rx{B} != new Rx{B}. | |
| V [Overflow] Not affected. | |
| BTS Test a bit and set it | |
| Operation: !Rx{B} -> Rx{B}, Z, C | |
| N [Negative] Not affected. | |
| Z [Zero] Set if old Rx{B} was clear, clear otherwise. | |
| C [Carry] Set if old Rx{B} != new Rx{B}. | |
| V [Overflow] Not affected. | |
| === 4.E. Branch Instructions =================================================== | |
| Branch instructions allow software to change the PC relative to its current | |
| value. Each branch instruction includes a signed byte value (the offset) in its | |
| bit pattern: | |
| BRA Bit Pattern | |
| FEDC BA98 7654 3210 | |
| bbbb bbbb OOOO Occc | |
| O = opcode | |
| b = signed 8-bit offset (-128 to +127) | |
| c = condition | |
| When a branch opcode is executed and its condition is true, the signed offset is | |
| added to the PC. Because instructions must be 16-bit aligned, the offset is | |
| shifted left by 1 (multiplied by 2) to allow for an effective range of -128 to | |
| +127 opcodes relative to the current PC. | |
| 1001 0ccc BXX NZCV | |
| 000 = BCC/BUF, Branch if carry clear AKA Unsigned Fewer Than ..0. | |
| 001 = BCS/BUH, Branch if carry set AKA Unsigned Higher Than or Same ..1. | |
| 010 = BNE, Branch if zero clear .0.. | |
| 011 = BEQ, Branch if zero set .1.. | |
| 100 = BPL/BSF, Branch if negative clear AKA Signed Fewer Than 0... | |
| 101 = BMI/BSH, Branch if negative set AKA Signed Higher Than Or Same 1... | |
| 110 = BVC, Branch if overflow clear ...0 | |
| 111 = BVS, Branch if overflow set ...1 | |
| 1001 1ccc BXX | |
| 000 = BUG, Branch if Unsigned Greater than .01. | |
| 001 = BSG, Branch if Signed Greater than 10.. | |
| 010 = Undefined .... | |
| 011 = Undefined .... | |
| 100 = Undefined .... | |
| 101 = Undefined .... | |
| 110 = Undefined .... | |
| 111 = BAW, Branch always .... | |
| === 4.F. Increment Instructions ================================================ | |
| ADI Add immediate value to register, carry is ignored. | |
| Operation: Rx + M -> Rx, C | |
| M is a 5-bit value + 1, for a range of ($01-$20). | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| DEC Decrement register by 1. | |
| Operation: Rx + M -> Rx, C | |
| This operation is an assembler macro for SBI Rx, $01 | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| INC Increment register by 1. | |
| Operation: Rx + M -> Rx, C | |
| This operation is an assembler macro for ADI Rx, $01 | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| SBI Subtract immediate value from register, carry is ignored. | |
| Operation: Rx + M -> Rx, C | |
| M is a 5-bit value + 1, for a range of ($01-$20). | |
| N [Negative] Set if bit 15 is set. | |
| Z [Zero] Set if Rx == 0. | |
| C [Carry] Set if overflow in bit 15. | |
| V [Overflow] Set if sign bit (bit 15) is incorrect. | |
| === 4.G. Jump & Call Instructions ============================================== | |
| JMP Unconditional Jump to new address. | |
| If jump is 'near' (far bit clear): | |
| 1. PC is set to CS[PC+2]. | |
| 2. Execution continues. | |
| If jump is 'far' (far bit set): | |
| 1. If YCPU is in user mode, raise UnPrivFault interrupt. | |
| 2. PC is set to CS[PC+2]. | |
| 3. CS segment lo word is set to CS[PC+4]. | |
| 4. CS segment hi word is set to CS[PC+6]. | |
| 5. Execution continues. | |
| JSR Unconditional Jump, saving return address. | |
| If jump is 'near' (far bit clear): | |
| 1. PC is pushed to the stack. [PC is the address of the NEXT operation] | |
| 2. PC is set to the value of M. | |
| 3. Execution continues. | |
| If jump is 'far' (far bit set): | |
| 1. If YCPU is in user mode, raise UnPrivFault interrupt. | |
| 2. CS segment hi word is pushed to stack. | |
| 3. CS segment lo word is pushed to stack. | |
| 4. PC is pushed to stack. [NB: PC is the address of the NEXT operation] | |
| 5. PC is set to CS[PC+2]. | |
| 6. CS segment lo word is set to CS[PC+4]. | |
| 7. CS segment hi word is set to CS[PC+6]. | |
| 8. Execution continues. | |
| === 4.H. Stack Instructions ==================================================== | |
| The following registers can be specified for Stack Instructions: | |
| R0-R7, A-D, W-Z, FL, PC, PS, SP, USP. Specifying a register | |
| twice (ex. R0 and A) will result in only one value popped to or pushed from | |
| that register. | |
| There are two separate instructions for pop and two for pull, each addressing a | |
| different set of registers. The first operation pops or pulls the eight general | |
| purpose registers, R0-R7. The second operation pops or pulls processor control | |
| registers SP, Fl, PC, PS, USP. | |
| Two notes on pushing and pulling the stack pointers. First, 'SP' and 'USP' is | |
| the value of these stack pointers BEFORE the operation. Thus if SP is $1000 and | |
| the operation 'PSH SP' is called, SP will now be $0FFF and the first value on | |
| the stack will be $1000. Second, 'SP' equates to the current stack pointer, and | |
| thus could be either USP or SSP depending on the mode of the processor. | |
| Executing 'PSH USP, SP' in user mode will push USP to the stack twice; the same | |
| instruction in supervisor mode will push both USP and SSP to the stack. | |
| Note that pushing and pulling 'PS', the processor status register, is a | |
| privileged operation. Attempting to push or pull this register in user mode | |
| will result in all other specified registers being pushed or pulled, followed by | |
| an 'Unprivileged opcode' interrupt. | |
| An assembler should transform a stack operation that includes registers from | |
| these two different register groups should split the operation into two | |
| separate instructions as follows: general purpose registers should always be | |
| popped first, and pushed last. Thus these two example instructions: | |
| PSH R0, R1, SP, PC | |
| POP R0, R1, SP, PC | |
| Should be transformed into: | |
| PSH SP, PC | |
| PSH R0, R1 | |
| POP R0, R1 | |
| POP SP, PC | |
| POP Pop values from the Stack into registers | |
| Syntax: Pop Rx[,Rx,Rx...] | |
| The processor sequentially loads values from the stack to the registers | |
| specified. Regardless of the order of the registers specified in the | |
| instruction, the registers are always popped in the following order: | |
| Bit pattern 0: R7, R6, R5, R4, R3, R2, R1, R0 | |
| Bit pattern 1: FL, PC, PS, USP, SP | |
| PSH Push values from registers to the Stack | |
| Syntax: Pop Rx[,Rx,Rx...] | |
| The processor sequentially saves a number of values from the stack equal to | |
| the number of registers specified. | |
| Regardless of the order of the registers specified in the instruction, the | |
| values registers are always pushed in the following order: | |
| Bit pattern 0: R0, R1, R2, R3, R4, R5, R6, R7 | |
| Bit pattern 1: SP, USP, PS, PC, FL | |
| STX Manipulate the stack with an immediate value. | |
| Syntax: STX [-$80 to $7F] | |
| The signed offset is added to SP. Because stack values must be 16-bit aligned, | |
| the offset is shifted left by 1 bit (multiplied by 2) to allow for an effective | |
| range of -256 to +254 bytes (-128 to +127 stack positions) relative to the | |
| current value of SP. | |
| === 4.I. Processor Function Instructions ======================================= | |
| CLF Clears bit(s) in the FL register. | |
| Syntax: CLF [N][,C][,Z][,V] | |
| The specified bits are cleared in the FL register. Any combination of the | |
| possible bits may be specified in a single instruction. | |
| HWQ Sends a message to the Hardware Bus. | |
| Syntax: HWQ $00 | |
| Sends a message with the specified identified to the Hardware Bus. This may | |
| query the bus directly, or send a message to a hardware device. | |
| LSG Load Segment Register from Stack | |
| Syntax: LSG [CS/DS/ES/SS/IS][_/S/U] | |
| Pulls two 16-bit words from the stack. Loads these values as a little-endian | |
| 32-bit value into the specified register. A programmer may indicate which of | |
| the nine segment registers should be loaded as follows: | |
| LSG CS or LSG CSS ; loads Supervisor Code Segment from Stack | |
| LSG DS or LSG DSS ; loads Supervisor Data Segment from Stack | |
| LSG ES or LSG ESS ; loads Supervisor Extra Data Segment from Stack | |
| LSG SS or LSG SSS ; loads Supervisor stack Segment from Stack | |
| LSG CSU ; loads User Code Segment from Stack | |
| LSG DSU ; loads User Data Segment from Stack | |
| LSG ESU ; loads User Extra Data Segment from Stack | |
| LSG SSU ; loads User Stack Segment from Stack | |
| LSG IS ; loads Interrupt Segment from Stack | |
| RTI Return from Interrupt | |
| Returns from an interrupt. This instruction is supervisor only. | |
| See 3.D.8. for a description of this opcode's function. | |
| RTS Return from Subroutine | |
| Returns from a code subroutine. Far returns are supervisor only. | |
| If return is 'near' (far bit clear): | |
| 1. PC is popped from the stack. | |
| 2. Execution continues. | |
| If return is 'far' (far bit set): | |
| 1. If YCPU is in user mode, raise UnPrivFault interrupt. | |
| 2. PC is popped from stack. | |
| 3. CS segment lo word is popped from stack. | |
| 4. CS segment hi word is popped from stack. | |
| 5. Execution continues. | |
| SEF Sets bit(s) in the FL register. | |
| Syntax: SEF [N][,C][,Z][,V] | |
| The specified bits are set in the FL register. Any combination of the | |
| possible bits may be specified in a single instruction. | |
| SLP Halts the processor until it receives an interrupt. | |
| This instruction is supervisor only. | |
| Syntax: SLP | |
| Places the processor into a halted state. No further instructions will be | |
| executed until the processor is interrupted (by the RTC or a hardware interrupt) | |
| at which point the processor will exit the halted state and continue execution | |
| after the interrupt is handled. | |
| SSG Store Segment Register to Stack | |
| Syntax: SSG [CS/DS/ES/SS/IS][_/S/U] | |
| Pushes the value of the indicated segment register to the stack as two 16-bit | |
| word values. A programmer may indicate which of the nine segment registers | |
| should be stored using the mnemonic seen in the LSG instruction description. | |
| SWI Call Software Interrupt | |
| Raises SOFTWARE INTERRUPT. | |
| See 3.D.3. for a description of this opcode's function. | |
| ### 5. History ################################################################# | |
| Please refer to the file 'ycpu history.txt' for a complete history of revisions | |
| to the YCPU specification. |