Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
cpu [2021/04/11 20:15] – [Addressing modes] simercpu [2022/11/12 14:57] (current) – [Registers] pulkomandy
Line 1: Line 1:
 ====== Sources of information ====== ====== Sources of information ======
  
- +Instruction set documentation archived from "unSP Programmer's Guide" PDF from the unSP IDE installation - {{ :unsp_programmer_s_guide.pdf  |local copy}}
-[[http://web.archive.org/web/20061022060454/http://mcu.sunplusmcu.com/soft/SPMC75XV18_pro.pdf|Instruction set documentation]] archived from sunplus website (chapter 19) - {{ :spmc75xv18_pro.pdf |local copy}}+A good overview can also be found in {{ ::unsp_isa-1.2.pdf | this document}}.
  
 ====== CPU ====== ====== CPU ======
  
-The V-Smile processor is a Sunplus uN'SP implementing version **1.1** of the ISA (source: this is how the SPG200 projects in uN'SP IDE are configured).+The V-Smile processor is a Sunplus µ'nSP implementing version **1.1** of the ISA (source: this is how the SPG200 projects in µ'nSP IDE are configured).
  
-The documentation below was extracted from the datasheet of another chip that implements a later version (1.2). Instructions that are available only in that later version are annotated to avoid confusion, but kept for reference in case it is useful to someone else. 
- 
-This document does not include information about uN'SP 2.0 architecture which is irrelevant to us and possibly not compatible (there are more registers, which would not fit the existing instruction format). 
 ===== Registers ===== ===== Registers =====
  
Line 26: Line 23:
 R3 stores the lower half and R4 stores the upper half. R3 stores the lower half and R4 stores the upper half.
  
-There is also a 4-bit shift buffer (SB) register used by the shift and rotate addressing modes. +There is also a 4-bit shift buffer (SB) register used by the shift and rotate addressing modes. There are separate SB registers for normal, FIQ and interrupt mode, which gets automatically switched
-==== Shadow Registers ====+ 
 +The BP register has a special addressing mode with a 6-bit immediate offset. It is usually (for example by unsp IDE C compiler) used as a frame pointer, to access a function local variables efficiently. But it can also be used as a normal register if needed. 
 + 
 +SP is generally used as a stack pointer but can be used for other things occasionally. When using the PUSH and POP instructions, the stack grows downwards (PUSH decrements SP) and the stack pointer points to the first empty space below the stack.
  
-**Only in ABI 1.2**+As a result, the typical organization of the stack in VTech code is:
  
-Registers R1-R4 have 'shadow' copies that can be enabled via the ''SECBANK'' instruction. When enabled, all reads and writes to R0-R4 are redirected to SR1-SR4. This can be used to avoid backing up, and restoring registers during Interrupt routines.+^Address^ Contents       ^ Notes                              ^ 
 +| NNNF  | Parameter 0    | Pushed by caller                   | 
 +| NNNE  | Parameter 1    |                                    | 
 +| NNND  | PC (from CALL) | Saved by CALL                      | 
 +| NNNC  | SR (from CALL) | Saved by CALL                      | 
 +| NNNB  | R4             | Saved by PUSH in function prelude 
 +| NNNA  | R3             | (and more registers as needed)     | 
 +| NNN9  | Local variable | Space allocated by decrementing SP | 
 +| NNN8  | Local variable | <BP points here                  | 
 +| NNN7  | Empty          | <SP points here                  |
  
 +The SP can move when calling other functions, interrupts, ... or when saving registers inside the function code. But BP doesn't move and can be used to access both local variables and function parameters.
 +
 +The parameters are usually removed by the caller (by incrementing SP). It would also be possible to use a POP including SR and PC to return from the function while clearing parameters, but this requires loading them into registers, which is not always desirable since registers are rather used for return values.
 ==== Status Register ==== ==== Status Register ====
  
Line 45: Line 57:
 |10-15|DS  |Data Segment |Auto incremented with pre/post inc/dec addressing mode as needed | |10-15|DS  |Data Segment |Auto incremented with pre/post inc/dec addressing mode as needed |
  
- 
-==== Flags register ==== 
- 
-**Only in ABI 1.2** 
- 
-This register is not accessible as a general purpose register. It can be written to by some specific instructions. 
- 
-^16^15^14 ^13 ^12 ^10-7^6^5^4  ^3-0    ^ 
-|- |AQ|BNK|FRA|FIR|SB  |F|I|INE|IRQ PRI| 
- 
-  * AQ: Flag for DIV/DIVS instructions 
-  * BNK: Set when the shadow registers are active (''SECBANK ON'') 
-  * FRA: Fraction mode 
-  * FIR: FIR_MOV mode 
-  * SB: shift buffer used by the ''SHIFT'' instruction. It makes it easy to shift values that use more than 16 bits 
-  * F: FIQ enable (set by the ''INT'' and ''FIQ'' instructions) 
-  * I: IRQ enable (set by the ''INT'' and ''IRQ'' instructions) 
-  * INE: IRQ nesting mode 
-  * IRQ PRI: current IRQ priority 
- 
-In ABI 1.1 and older, there are separate SB registers for normal, FIQ and interrupt mode. The F, I and FIR flags exist, but are not exposed as a register. 
 ====== Address Space ====== ====== Address Space ======
  
-The memory map of the uN'SP is split into 64K sized pages. The entire 4M address space of the CPU is divided into 64 pages (0x00-0x3F). The current page can be selected via the segment registers, CS (for instruction fetch) and DS (for data operations).+The memory map of the µ'nSP is split into 64K sized pages. The entire 4M address space of the CPU is divided into 64 pages (0x00-0x3F). The current page can be selected via the segment registers, CS (for instruction fetch) and DS (for data operations).
  
 When code execution reaches the end of the current page, the CS register is auto-incremented by the hardware. When code execution reaches the end of the current page, the CS register is auto-incremented by the hardware.
Line 89: Line 80:
 |0xFFFF|IRQ7 | |0xFFFF|IRQ7 |
  
 +See http://vtech.pulkomandy.tk/doku.php?id=memory_map&s%5B%5D=irq#interrupts for details about the interruptions usage.
 ====== Instruction Set ====== ====== Instruction Set ======
  
-These tables detail the instruction both in the format used by the official uN'SP toolchain as well as the mnemonic form used by the free for non-commercial use vasm.+These tables detail the instruction both in the format used by the official µ'nSP toolchain as well as the mnemonic form used by the free for non-commercial use vasm.
  
 NOTE: Unless otherwise specified, instructions that operate on memory ignore DS and only operate on page 0 (0x0000-0xFFFF). Instruction varients that allow a "D:" prefix generate a full 22-bit address via ''%%(DS << 16 | addr)%%'' NOTE: Unless otherwise specified, instructions that operate on memory ignore DS and only operate on page 0 (0x0000-0xFFFF). Instruction varients that allow a "D:" prefix generate a full 22-bit address via ''%%(DS << 16 | addr)%%''
Line 99: Line 91:
 ==== Load ==== ==== Load ====
  
-^Instruction        ^Smasm Form            ^Notes                               ^Flags Affected^ +^Instruction            ^naken_asm form           ^Notes                               ^Flags Affected^ 
-|Rd = Value         |mov rd, value         |6 and 16-bit variants available     |NZ            | +|%%Rd = Value         %%|%%ld rd, value         %%|6 and 16-bit variants available      NZ            | 
-|Rd = [BP + offset] |mov rd, [BP + offset] |Offset is limited to 6 bits         |NZ            | +|%%Rd = [BP + offset] %%|%%ld rd, [BP + offset] %%|Offset is limited to 6 bits          :::            | 
-|Rd = [addr]        |mov rd, [addr]        |6 and 16-bit variants available     |NZ            | +|%%Rd = [addr]        %%|%%ld rd, [addr]        %%|6 and 16-bit variants available      :::            | 
-|Rd = Rs            |mov rd, rs            |                                    |NZ            | +|%%Rd = Rs            %%|%%ld rd, rs            %%|                                    |  :::            | 
-|Rd = {D:}[Rs]      |mov rd, {D:}[rs]      |Optional data-segment qualifier (D:)|NZ            | +|%%Rd = {D:}[Rs]      %%|%%ld rd, {D:}[rs]      %%|Optional data-segment qualifier (D:)|  :::            | 
-|Rd = {D:}[++Rs]    |mov rd, {D:}[++rs]    | :::  |NZ +|%%Rd = {D:}[++Rs]    %%|%%ld rd, {D:}[++rs]    %%| :::                                 :::            
-|Rd = {D:}[Rs--]    |mov rd, {D:}[rs--]    | :::  |NZ +|%%Rd = {D:}[Rs--]    %%|%%ld rd, {D:}[rs--]    %%| :::                                 :::            
-|Rd = {D:}[Rs++]    |mov rd, {D:}[rs++]    | :::  |NZ |+|%%Rd = {D:}[Rs++]    %%|%%ld rd, {D:}[rs++]    %%| :::                                 :::            |
 ==== Store ==== ==== Store ====
  
-^Instruction          ^Smasm Form             ^Notes                               ^Flags Affected^ +^Instruction            ^naken_asm form           ^Notes                               ^Flags Affected^ 
-|[BP + offset] = Rd   |mov [BP + offset], rd  |Offset is limited to 6 bits                      | +|%%[BP + offset] = Rd %%|%%st rd, [BP + offset] %%|Offset is limited to 6 bits                      | 
-|[addr] = Rd          |mov [addr], rd         |                                    |              | +|%%[addr] = Rd        %%|%%st rd, [addr]        %%|                                    |              | 
-|{D:}[Rs] = Rd        |mov {D:}[rs], rd       |Optional data-segment qualifier (D:)|              | +|%%{D:}[Rs] = Rd      %%|%%st rd, {D:}[rs]      %%|Optional data-segment qualifier (D:)|              | 
-|{D:}[++Rs] = Rd      |mov {D:}[++rs], rd     | :::                                |              | +|%%{D:}[++Rs] = Rd    %%|%%st rd, {D:}[++rs]    %%| :::                                |              | 
-|{D:}[Rs--] = Rd      |mov {D:}[rs--], rd     | :::                                |              | +|%%{D:}[Rs--] = Rd    %%|%%st rd, {D:}[rs--]    %%| :::                                |              | 
-|{D:}[Rs++] = Rd      |mov {D:}[rs++] = rd    | :::                                |              |+|%%{D:}[Rs++] = Rd    %%|%%st rd, {D:}[rs++]    %%| :::                                |              |
 ==== Push/Pop ==== ==== Push/Pop ====
  
-^Instruction          ^Smasm Form                                     ^Notes        ^Flags Affected^ +^Instruction              ^naken_asm form       ^Notes                                       ^Flags Affected^ 
-|PUSH Rx, Ry to [Rs]  |push rx-ry [rs] |rx-ry signifies a range of registers to push|              | +|%%PUSH Rx, Ry to [Rs]  %%|%%push rx-ry[rs] %%|rx-ry signifies a range of registers to push|              | 
-|PUSH Rx to [Rs]      |push rx, [rs]   |Push a single register                      |              | +|%%PUSH Rx to [Rs]      %%|%%push rx, [rs]    %%|Push a single register                      |              | 
-|POP Rx, Ry from [Rs] |pop rx-ry [rs]  |rx-ry signifies a range of registers to pop |              | +|%%POP Rx, Ry from [Rs] %%|%%pop rx-ry[rs]  %%|rx-ry signifies a range of registers to pop |              | 
-|POP Rx from [Rs]     |pop rx, [rs]    |Pop a single register                                    |+|%%POP Rx from [Rs]     %%|%%pop rx, [rs]     %%|Pop a single register                                    | 
 + 
 +The stack grows downwards (towards lower addresses). 
 +Push does post-decrement so SP points to the unused entry at the top of the stack. 
 + 
 +**Values before pushing:** 
 + 
 +^Address ^Content ^ 
 +|FFFF    |XXXX    ^ 
 +|FFFE    |---     ^ 
 +|FFFD    |---     ^ 
 + 
 +SP = FFFE 
 + 
 +''PUSH BP, [SP]'' 
 + 
 +**Values after pushing:** 
 + 
 +^Address ^Content ^ 
 +|FFFF    |XXXX    ^ 
 +|FFFE    |**BP** 
 +|FFFD    |---     ^ 
 + 
 +SP = FFFD
 ===== ALU operations ===== ===== ALU operations =====
  
 All these operations have similar syntax and support the same addressing modes All these operations have similar syntax and support the same addressing modes
  
-^Mnemonic        ^smasm syntax      ^Description         ^Flags affected ^ +^Mnemonic           ^naken_asm form  ^Description                           ^Flags affected ^ 
-| Rd += Rs       |ADD Rd, Rs        |Add                 |  NZSC  | +|%%Rd += Rs       %%|%%ADD Rd, Rs  %%|Add                                   |  NZSC  | 
-| Rd += Rs,carry |ADC Rd, Rs        |Add with carry      | ::: | +|%%Rd += Rs,carry %%|%%ADC Rd, Rs  %%|Add with carry                         :::   
-| Rd -= Rs       |SUB Rd, Rs        |Subtract            | ::: | +|%%Rd -= Rs       %%|%%SUB Rd, Rs  %%|Subtract                               :::   
-| Rd -= Rs,carry |SBC Rd, Rs        |Subtract with carry | ::: | +|%%Rd -= Rs,carry %%|%%SBC Rd, Rs  %%|Subtract with carry                    :::  
-| CMP Rd, Rs     |CMP Rd, Rs        |Compare (same effect on flags as sub) | ::: | +|%%CMP Rd, Rs     %%|%%CMP Rd, Rs  %%|Compare (same effect on flags as SUB) |  :::  
-| Rd = -Rs       |NEG Rd, Rs        |Negate              |  NZ   | +|%%Rd = -Rs       %%|%%NEG Rd, Rs  %%|Negate                                |  NZ   | 
-Rd %%^%%= Rs       |XOR Rd, Rs        |Exclusive OR        | ::: | +|%%Rd ^= Rs       %%|%%XOR Rd, Rs  %%|Exclusive OR                           :::  
-Rd %%|%%= Rs       |OR Rd, Rs         |Bitwise OR          | ::: | +|%%Rd |= Rs       %%|%%OR Rd, Rs   %%|Bitwise OR                             :::  
-| Rd &= Rs       |AND Rd, Rs        |Bitwise AND         | ::: | +|%%Rd &= Rs       %%|%%AND Rd, Rs  %%|Bitwise AND                            :::  
-| Test Rd, Rs    |TEST Rd, Rs       |Same effect on flags as bitwise AND| ::: |+|%%Test Rd, Rs    %%|%%TEST Rd, Rs %%|Same effect on flags as bitwise AND    :::  |
  
 ==== Addressing modes ==== ==== Addressing modes ====
Line 144: Line 159:
 For all ALU operations, the following addressing modes are available: For all ALU operations, the following addressing modes are available:
  
-^Syntax          ^smasm syntax      ^Description                                                                ^ +^Syntax                ^naken_asm form           ^Description                                                                ^ 
-|%% R1 += R2         %%|%% ADD R1, R2         %%|Register                                                                   | +|%% R1 += R2         %%|%% ADD R1, R2          %%|Register                                                                   | 
-|%% R1 += R2 ASR 1   %%|%% ADD R1, R2 ASR 1   %%|Register with shift (ASR, LSL, LSR, ROR or ROLup to 4 bits               +|%% R1 += R2 ASR 1   %%|%% ADD R1, R2 ASR 1    %%|Register with arithmetic right shift up to 4 bits                          | 
-|%% R1 += 23         %%|%% ADD R1, #23        %%|6-bit immediate value (Rd cannot be PC)                                    | +|%% R1 += R2 LSL 1   %%|%% ADD R1R2 LSL 1    %%|Register with logical left shift up to 4 bits                              | 
-|%% R1 = R2 + 1234   %%|%% ADD R1, R2, #1234  %%|3-operand 16-bit immediate                                                 | +|%% R1 += R2 LSR 1   %%|%% ADD R1R2 LSR 1    %%|Register with logical left shift up to 4 bits                              | 
-|%% R1 += [12]       %%|%% ADD R1, [12]       %%|Direct (get value at 6-bit address 12)                                     | +|%% R1 += R2 ROL 1   %%|%% ADD R1R2 ROL 1    %%|Register with 20-bit left rotation through SB up to 4 bits                 | 
-|%% R1 = R2 + [1234] %%|%% ADD R1, R2, [1234] %%|Direct 3-operand (get values at R2 and 16-bit address 1234)                | +|%% R1 += R2 ROR 1   %%|%% ADD R1, R2 ROR 1    %%|Register with 20-bit right rotation through SB up to 4 bits                
-|%% [1234] = Rd Rs %%|%% ADD [1234],Rd,Rs   %%|Direct-store 3-operand                                                     | +|%% R1 += 23         %%|%% ADD R1, #23         %%|6-bit immediate value (Rd cannot be PC)                                    | 
-|%% R1 += [R2]       %%|%% ADD R1, [R2]       %%|Indirect (register used as pointer)                                        | +|%% R1 = R2 + 1234   %%|%% ADD R1, R2, #1234   %%|3-operand 16-bit immediate                                                 | 
-|%% R1 += [R2--]     %%|%% ADD R1, [R2--]     %%|  ... with post-decrement                                                  | +|%% R1 += [12]       %%|%% ADD R1, [12]        %%|Direct (get value at 6-bit address 12)                                     | 
-|%% R1 += [R2++]     %%|%% ADD R1, [R2++]     %%|  ... with post-increment                                                  | +|%% R1 = R2 + [1234] %%|%% ADD R1, R2, [1234]  %%|Direct 3-operand (get values at R2 and 16-bit address 1234)                | 
-|%% R1 += [++R2]     %%|%% ADD R1, [++R2]     %%|  ... with pre-increment                                                   | +|%% [1234] = R1 R2 %%|%% ADD [1234], R1R2  %%|Direct-store 3-operand                                                     | 
-|%% R1 += D:[R2]     %%|%% ADD R1, D:[R2]     %%|  ... in data segment (address is (DS << 16) %%|%% R2))                    | +|%% R1 += [R2]       %%|%% ADD R1, [R2]        %%|Indirect (register used as pointer)                                        | 
-|%% R1 += D:[R2--]   %%|%% ADD R1, D:[R2--]   %%|  ... with post-decrement in data segment                                  | +|%% R1 += [R2--]     %%|%% ADD R1, [R2--]      %%|  ... with post-decrement                                                  | 
-|%% R1 += D:[R2++]   %%|%% ADD R1, D:[R2++]   %%|  ... with post-increment in data segment                                  | +|%% R1 += [R2++]     %%|%% ADD R1, [R2++]      %%|  ... with post-increment                                                  | 
-|%% R1 += D:[++R2]   %%|%% ADD R1, D:[++R2]   %%|  ... with pre-increment in data segment                                   | +|%% R1 += [++R2]     %%|%% ADD R1, [++R2]      %%|  ... with pre-increment                                                   | 
-|%% R1 += [BP+12]    %%|%% ADD R1, [BP+12]    %%|6-bit displacement from BP (Rd cannot be PC)                               |+|%% R1 += D:[R2]     %%|%% ADD R1, D:[R2]      %%|  ... in data segment (address is (DS << 16) %%|%% R2))                    | 
 +|%% R1 += D:[R2--]   %%|%% ADD R1, D:[R2--]    %%|  ... with post-decrement in data segment                                  | 
 +|%% R1 += D:[R2++]   %%|%% ADD R1, D:[R2++]    %%|  ... with post-increment in data segment                                  | 
 +|%% R1 += D:[++R2]   %%|%% ADD R1, D:[++R2]    %%|  ... with pre-increment in data segment                                   | 
 +|%% R1 += [BP+12]    %%|%% ADD R1, [BP+12]     %%|6-bit displacement from BP (Rd cannot be PC)                               |
  
 It is possible to combine indirect with data segment and increments and decrements in the same instruction. The data segment will then be automatically updated in case the increment or decrement wraps. It is possible to combine indirect with data segment and increments and decrements in the same instruction. The data segment will then be automatically updated in case the increment or decrement wraps.
Line 166: Line 185:
 The shift operations use the shift buffer (see "shift operations" section below). In particular the ROR and ROL operations do a 20-bit rotation resulting in bits from the shift buffer moving into the destination register. The shift operations use the shift buffer (see "shift operations" section below). In particular the ROR and ROL operations do a 20-bit rotation resulting in bits from the shift buffer moving into the destination register.
  
-===== Bit shift instructions ===== +=== Bit shift addressing modes ===
- +
-**Only in ISA 1.2** +
- +
-Flags affected: NZ +
- +
-Unlike the shift embedded in the parameters of an ALU operation, this is an independant opcode. The smasm syntax makes this clear, in the xasm syntax it can be hard to distinguish the different cases. +
- +
-The main differences in behavior are: +
-  * This instruction can shift by up to 16 bits, instead of just 4 +
-  * The shift operand can be a constant, but also a register, for variable shifts+
  
 Given a starting register like this: Given a starting register like this:
  
-^Bits 15-0^ +^  ^Bits 15-0^ 
-|Rs15-Rs0 |+^Rs|Rs15-Rs0 |
  
-And the SR bits in the flags register:+And the SB bits:
  
-^Bits 3-0^ +^  ^Bits 3-0^ 
-|SR3-SR0 |+^SB|SB3-SB0 |
  
 The result of the shift operations are (for a shift by 3 bits): The result of the shift operations are (for a shift by 3 bits):
  
-==== ASR ====+== ASR ==
  
 Arithmetic shift right (signed divide by two) Arithmetic shift right (signed divide by two)
  
-^Bits 15-13^Bits 12-0^ +^  ^Bits 15-13^Bits 12-0^ 
-|Rs15      |Rs15-Rs3 |+^Rs|Rs15      |Rs15-Rs3 |
  
-^Bits 3-1^Bit 0^ +^  ^Bits 3-1^Bit 0^ 
-|Rs2-Rs0 |SR3  |+^SB|Rs2-Rs0 |SB3  |
  
-==== LSL ====+== LSL ==
  
 Logical shift left (multiply by two) Logical shift left (multiply by two)
  
-^Bits 15-3^Bits 2-0^ +^  ^Bits 15-3^Bits 2-0^ 
-|Rs12-Rs0 |000 |+^Rs|Rs12-Rs0 |0       |
  
-^Bit 3^Bit 2-0^ +^  ^Bit 3^Bit 2-0  
-|SR0  |Rs15-Rs13|+^SB|SB0  |Rs15-Rs13|
  
-==== LSR ====+== LSR ==
  
 Logical shift right (unsigned divide by two) Logical shift right (unsigned divide by two)
  
-^Bits 15-13^Bits 12-0^ +^  ^Bits 15-13^Bits 12-0^ 
-|0      |Rs15-Rs3 |+^Rs|0      |Rs15-Rs3    |
  
-^Bits 3-1^Bit 0^ +^  ^Bits 3-1^Bit 0^ 
-|Rs2-Rs0 |SR3  |+^SB|Rs2-Rs0 |SB3  |
  
-==== ROL ====+== ROL ==
  
-Rotate left+Rotate left through shift buffer
  
-^Bits 15-3^Bits 2-0^ +^  ^Bits 15-3^Bits 2-0^ 
-|Rs12-Rs0 |SR3-SR1 |+^Rs|Rs12-Rs0 |SB3-SB1 |
  
-^Bit 3^Bit 2-0^ +^  ^Bit 3^Bit 2-0  
-|SR0  |Rs15-Rs13|+^SB|SB0  |Rs15-Rs13|
  
-==== ROR ====+== ROR ==
  
-Rotate right+Rotate right through shift buffer
  
-^Bits 15-13^Bits 12-0^ +^  ^Bits 15-13^Bits 12-0^ 
-|SR2-SR0   |Rs15-Rs3 |+^Rs|SB2-SB0   |Rs15-Rs3 |
  
-^Bits 3-1^Bit 0^ +^  ^Bits 3-1^Bit 0^ 
-|Rs2-Rs0 |SR3  |+^SB|Rs2-Rs0 |SB3  |
  
-==== ASR-OR, LSL-OR, LSR-OR ==== 
- 
-These operations do the shift as documented above, then OR it with the original register value. 
- 
-xasm syntax: 
- 
-''R1 |= R1 LSL R2'' 
- 
-==== 32-bit shifts ==== 
- 
-The assembler has a shorthand instruction for 32bit shifts (it is assembled as two consecutive 16bit instructions): 
- 
-''MR |= R4 asr 1'' 
- 
-FIXME 
-  * The documentation says ROL and ROR can't use R4 as a source register? 
-===== Bit operations ===== 
- 
-**Only in ISA 1.2** 
- 
-Flag affected: Z 
- 
-''TSTB'' - Test bit 
- 
-''CLRB'' - Clear bit 
- 
-''SETB'' - Set bit 
- 
-''INVB'' - Flip bit 
- 
-The destination operand can be a register, or an indirect register with or without D: prefix. 
-The source operand can be a register or an immediate value (in the range 0-15). If it is a register only the 4 LSB are used. 
- 
-The Z flag is set according to the value of the bit **before** the operation is executed. 
- 
-''CLRB R3,2'' Copies bit 2 of R3 in the Z flag, then clears the bit in the register. 
- 
-''TSTB D:[R1],13'' copies bit 13 of D:[R1] in the Z flag. 
 ===== Multiplication and division ===== ===== Multiplication and division =====
  
Line 284: Line 255:
 Multiplication result is stored in R3 and R4 (the register pair is called MR) Multiplication result is stored in R3 and R4 (the register pair is called MR)
  
-^Instruction          ^Smasm Form^Notes                                                                                          ^Flags Affected^ +^Instruction               ^naken_asm form           ^Notes                                                                                           ^Flags Affected^ 
-|MR = Rd x Rs         |MUL Rd, Rs      |Signed multiplication                                                                          |              | +|%%MR = Rd x Rs          %%|%%MUL.SS Rd, Rs        %%|Signed multiplication                                                                           |              | 
-|MR = Rd x Rs,us      |MULU Rd, Rs     |Rd is unsigned, Rs is signed                                                                   | :::          | +|%%MR = Rd x Rs,us       %%|%%MUL.US Rd, Rs        %%|Rd is unsigned, Rs is signed                                                                    | :::          | 
-|MR = Rd x Rs,uu      |MULUU Rd, Rs     |Unsigned multiplication **ISA 1.2 only**                                                      | :::          | +|%%MR = [Rd] x [Rs],   %%|%%MAC [Rd][Rs]N    %%|Multiply-accumulate two sets of N signed values pointed by Rd and Rs                                         
-|MR = [Rd] x [Rs],  |MACU (Rd),(Rs),|Multiply-accumulate two sets of N signed values pointed by Rd and Rs                          S            +|%%MR = [Rd] x [Rs],us,%%|%%MAC.US [Rd][Rs]N %%|Multiply-accumulate two sets of N values pointed by Rd (unsigned values) and Rs (signed values) | :::          |
-|MR = [Rd] x [Rs],us,n|MAC (Rd),(Rs),n|Multiply-accumulate two sets of N values pointed by Rd (unsigned values) and Rs (signed values) | :::          | +
-|MR = [Rd] x [Rs],uu,n|MAC (Rd),(Rs),n|Multiply-accumulate two sets of N unsigned values pointed by Rd and Rs **ISA 1.2 only**         | :::          | +
- +
-Multiply-accumulate operations do the computation with 36-bit precision. The result is stored in MR and the shift buffer in the flags register. S flag is set if there is an overflow. +
-==== Division ==== +
- +
-**Only in ISA 1.2** +
- +
-''DIVS MR, R2'' +
- +
-''DIVQ MR, R2'' +
- +
-These instructions implement 32-bit division. There are two divide primitives, DIVS +
-and DIVQ. A single precision divide, with a 32-bit numerator and a 16-bit +
-denominator, yielding a 16-bit quotient, executes in 16*3 cycles. Higher precision +
-divides are also possible. The division can be either signed or unsigned, but both the +
-numerator and denominator must be the same. Place the 32-bit numerator at R4: R3, +
-the 16-bit denominator at R2 and clear the AQ flag then executed with the divide +
-primitives, DIVS and DIVQ. Repeated execution of DIVQ implements a non-restoring +
-conditional add-subtract division algorithm. At the conclusion of divide operation the +
-quotient will be placed at R3.+
  
 +Multiply-accumulate operations do the computation with 32-bit precision with the result is stored in MR. The Rd and Rs pointers will automatically be incremented by N.
 +The values of the array pointed to by the Rd array will each be moved one index forward when the FIR_MOV setting is enabled, see the FIR_MOV section for details.
 ==== FIR_MOV ==== ==== FIR_MOV ====
  
Line 317: Line 269:
 ''FIR_MOV OFF'' ''FIR_MOV OFF''
  
-Affects the FIR bit in the flags register.+Affects the FIR setting used by the MULS instructions.
  
-When enabled, the multiply-accumulate instructions automatically increment Rd and Rs by nWhen disabledthey do not change Rd and Rs.+When enabled, MULS instructions will modify the array pointed to by the Rd register after finishing the calculation by moving each value one index forward with the last value discarded and the first value left in placeThis can be used for automatically advancing the time step when implementing FIR filterswith the Rd array storing the input signal and the Rs array storing the weights.
  
-==== FRACTION ==== 
- 
-''FRACTION ON'' 
- 
-''FRACTION OFF'' 
- 
-**Only in ISA 1.2** 
- 
-When enabled, multiply operations shift the result left by 1 bit 
- 
-===== Other operations ===== 
- 
-==== EXP ==== 
- 
-**Only in ISA 1.2** 
- 
-''R1 = EXP R2'' 
- 
-Returns the number of sign bits in R2, that is, count the from the MSB the number of bits that all have the same value. 
-===== Data Segment Access ===== 
- 
-**Only in ISA 1.2** 
- 
-''DS = Rs'' 
- 
-''Rd = DS'' 
- 
-''DS = 12'' 
- 
-smasm syntax: 
- 
-''MOV DS, Rs'' 
- 
-''MOV Rd, DS'' 
- 
-''MOV DS, 12'' 
- 
-Set or Get the DS value from SR. The other 10 bits of Rd are set to 0. 
- 
-On older architecture versions, this has to be done manually by accessing SR like a normal register (masking with AND and OR). 
 ===== Program Flow ===== ===== Program Flow =====
  
Line 373: Line 285:
 The target address is stored as a 6 bit displacement and a separate bit indicating forward or backward jump. So this can only jump back and forward 63 addresses. The target address is stored as a 6 bit displacement and a separate bit indicating forward or backward jump. So this can only jump back and forward 63 addresses.
  
-^Instruction^Smasm Form^Notes              ^Flags Affected^ +^Instruction        ^Notes               ^Flags Affected^ 
-|JCC,JB,JNAE|          |Jump if C=0        |              | +|JB,JCC,JNAE label |Jump if C=0         |              | 
-|JCS,JNB,JAE|          |Jump if C=1        |              | +|JAE,JNB,JCS label |Jump if C=1         |              | 
-|JSC,JGE,JNL|          |Jump if S=0        |              | +|JGE,JNL,JSC label |Jump if S=0         |              | 
-|JSS,JNGE,JL|          |Jump if S=1        |              | +|JL,JNGE,JSS label |Jump if S=1         |              | 
-|JNE,JNZ             |Jump if Z=0        |              | +|JNE,JNZ label     |Jump if Z=0         |              | 
-|JZ,JE      |          |Jump if Z=1        |              | +|JE,JZ label       |Jump if Z=1         |              | 
-|JPL                 |Jump if N=0        |              | +|JPL label         |Jump if N=0         |              | 
-|JMI                 |Jump if N=1        |              | +|JMI label         |Jump if N=1         |              | 
-|JBE,JNA             |Jump if Z=1 or C=0 |              | +|JBE,JNA label     |Jump if Z=1 or C=0  |              | 
-|JNA        |          |Jump if Z=1 or C=0 |              | +|JA,JNBE label     |Jump if Z=0 and C=1 |              | 
-|JNBE,JA    |          |Jump if Z=0 and C=1|              | +|JLE,JNG label     |Jump if Z=1 or S=1  |              | 
-|JLE,JNG             |Jump if Z=1 or S=1 |              | +|JG,JNLE label     |Jump if Z=0 and S=0 |              | 
-|JNLE,JG             |Jump if Z=0 and S=0|              | +|JVC label         |Jump if N=S         |              | 
-|JVC                 |Jump if N=S        |              | +|JVS label         |Jump if N != S      |              | 
-|JVS                 |Jump if N != S     |              | +|JMP label         |Jump always         |              |
-|JMP                 |Jump always        |              |+
  
 xasm supports the syntax ''SJMP'' for "smart jump" that will automatically be converted to a jump + GOTO if the address is outside the reachable range for a normal jump. xasm supports the syntax ''SJMP'' for "smart jump" that will automatically be converted to a jump + GOTO if the address is outside the reachable range for a normal jump.
Line 402: Line 313:
  
 Because SR is pushed automatically, flags are always saved accross a CALL/RETF Because SR is pushed automatically, flags are always saved accross a CALL/RETF
- 
-=== Indirect call === 
- 
-**Only in ISA 1.2** 
- 
-''CALL MR'' 
- 
-The target address is formed from MR (R4 and R3). R4 contains the segment (loaded into CS) and R3 contains the offset (loaded into PC). 
  
 === GOTO === === GOTO ===
  
-Like a call, but does not save PC and SR on the stack. Both direct (ISA 1.1) and indirect (**ISA 1.2 only**) versions are available. +Like a call, but does not save PC and SR on the stack.
 In ISA 1.0, GOTO does not set the CS: so it is not possible to jump outside the current segment. In ISA 1.1 and above this problem is fixed. In ISA 1.0, GOTO does not set the CS: so it is not possible to jump outside the current segment. In ISA 1.1 and above this problem is fixed.
  
Line 428: Line 330:
  
 Jumps to the BREAK software IRQ handler. Jumps to the BREAK software IRQ handler.
- 
-=== NOP === 
- 
-Do nothing. 
  
 ===== Interrupt control ===== ===== Interrupt control =====
Line 437: Line 335:
 === IRQ enable/disable === === IRQ enable/disable ===
  
-^Instruction^Smasm Form^Notes                  ^Flags Affected^ +^Instruction ^Notes                   ^Flags Affected^ 
-|IRQ OFF             |Disable interrupts     |              | +|IRQ OFF     |Disable interrupts      |              | 
-|IRQ ON     |          |Enable interrupts      |              | +|IRQ ON      |Enable interrupts       |              | 
-|FIQ OFF             |Disable fast interrupts|              | +|FIQ OFF     |Disable fast interrupts |              | 
-|FIQ ON     |          |Enable fast interrupts |              | +|FIQ ON      |Enable fast interrupts  |              | 
-|INT FIQ             |Enable FIQ, disable IRQ|              | +|INT FIQ     |Enable FIQ, disable IRQ |              | 
-|INT FIQ,IRQ|          |Enable FIQ and IRQ     |              | +|INT FIQ,IRQ |Enable FIQ and IRQ      |              | 
-|INT IRQ             |Disable FIQ, enable IRQ|              | +|INT IRQ     |Disable FIQ, enable IRQ |              | 
-|INT OFF             |Disable FIQ and IRQ    |              | +|INT OFF     |Disable FIQ and IRQ     |              |
- +
-=== SECBANK === +
- +
-**Only in ISA 1.2** +
- +
-''SECBANK ON'' +
- +
-''SECBANK OFF'' +
- +
-Switches to the alternate registers SR1-SR4 or restores the normal R1-R4. +
- +
-The status is stored in the flags register. +
- +
-=== IRQNEST === +
- +
-**Only in ISA 1.2** +
- +
-''IRQNEST ON'' +
- +
-''IRQNEST OFF'' +
- +
-Enables IRQ nesting. IRQ will save the flags register on the stack (in addition to SR and PC) and the RETI instruction will restore it. +
- +
-The IRQ priority can be set in FR to determine which interruptions are allowed to happen. +
- +
-The status is stored in the INE bit of the flags register. +
- +
-=== Direct access to FR register === +
- +
-**Only in ISA 1.2** +
- +
-''FR = Rs'' +
- +
-''Rd = FR'' +
- +
-smasm syntax:+
  
-''MOV FR, Rs'' 
  
-''MOV Rd, FR'' 
  
cpu.1618164958.txt.gz · Last modified: 2021/04/11 20:15 by simer
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0