-
Instruction types by argument placement
11/27/2022 at 13:54 • 0 commentsThere are 19 ways the arguments are placed into instruction word(s), among them one without any arguments.
This systematization is for me to have a clearer picture for assembler development.
-
Register names
11/24/2022 at 13:23 • 0 commentsAmong 19 programmer-visible registers there are two main groups of 8 each and 3 special registers scattered around the CPU:
1) General Purpose Registers: 8 16-bit registers that are accessible to main ALU.
These registers are named r0, r1, r2, r3, r4, r5, r6 and r7.
2) Memory Pointer Registers: 8 16-bit registers combined in 4 pairs to hold 32-bit values. The registers are also accessible individually for data transfer.
Memory Pointer Pair (32-bit) names, they are used in Indirect Memory Access instructions, Load Immediate into Pointer instruction and Address Arithmetic instructions:
PC -- Program Counter, updated each time new instruction is fetched
SP -- Stack Pointer, provides address for storing current PC value when executing JSR instruction
FP -- Frame Pointer, can be used as additional pointer to manage program stack
BP -- Base Pointer, can be used as additional pointer, for example, to some data structure in memory, like object or array.
Individual Memory Pointer register (16-bit) names:
mp0, or PCH -- high word of PC pair
mp1, or PCL -- low word of PC pair
mp2, or SPH -- high word of SP pair
mp3, or SPL -- low word of SP pair
mp4, or FPH -- high word of FP pair
mp5, or FPL -- low word of FP pair
mp6, or BPH -- high word of BP pair
mp7, or BPL -- low word of BP pair
3) Status Register
SR -- this register is only 4-bits, it contains flags indicating ALU operation output characteristics, such as if there is a carry generated, or oveflow, or the resulting value is negative or zero.
It can have its value moved into or from one of GPR or MPR with special MOV operation.
4) Memory Data Buffer
MDB -- 16-bit register -- written to automatically whenever F2 state is active by the value of second word of 2-word instruction.
It can also be written to or read from to GPR or MPR manually with special MOV operation.
5) Interrupt Vector Base
IVB -- 16-bit register, used to provide the base address for an array of Interrupt Service Routines, is a high word of 32-bit address.
Can also be written to or read from to GPR or MPR with special MOV operation. The write is used for initial setup of system.
-
Labels
11/24/2022 at 10:29 • 0 commentsLabels are symbolic representations of particular addresses in memory that can have either instructions to jump to, or variables to be fetched or stored by some memory access instruction.
In assembly program label is indicated by colon ':' at the end of the first word (contiguous sequence of non-whitespace characters) in the line.
example_label: <some code>
Label can either precede the labeled instruction or variable, or be on the same line.
During first pass of the assembler, all labels are added to look-up table, which is used on second pass to inline actual values for instruction arguments instead of their symbolic representations.
-
Directives
11/24/2022 at 10:08 • 0 commentsFollowing assembler directives are used:
structural directives:
these directives determine the context for code that comes after them
.const -- optional block containing list of labeled constants -- primarily these are absolute addresses of memory mapped I/O ports
.text -- indicates start of proper code block, containing instruction sequence
.data -- indication of start of block containing static variables
comment directive
Anything starting with hash symbol (#) and ending with newline is considered a comment and is ignored.Example: # this whole line is comment LDi r0 0x01 #comment: this operation adds 1 to value in register r0
assignment directive:
= -- used as assignment statement in constants block
Example: .const #start of constants block constant_value = 0x1234
size directives:
these are used only in data segment
.string -- byte-sized array, containing ascii symbols, the value assigned to it is in quotes. At the end of string there is at least one byte with zero value (0x00, C-like string)
.word -- 16-bit numeric value
.dword -- 32-bit numeric value
.long -- 64-bit numeric valueExample: var_1: .word 0x1234 var_2: .dword 0x1234678 var_3: .long 0x1234567890123456 var_4: .string "example string, with \"quotes\" inside"
All parts should be on the same string.
-
Aliases
11/23/2022 at 06:31 • 0 commentsAliases are additional mnemonics for pseudo-instructions, which are substituted by assembler with proper instruction mnemonics right before translating to machine code.
For now, this is a "TO DO" list, to be implemented in assembler.
There are several groups of aliases:
Prefixes:
these are modifiers for MOV and LD/ST (LDr/STr) instructions that change the size of data transferred, this way it is easier to use/understand them.
Here is translation to proper instruction:
2W = SETPR 0 -- Move, Load or Store 2 words into 2 adjacent registers (aligned to even, e.g. r0 and r1, or r6 and r7)
4W = SETPR 1 -- Move, Load or Store 4 words into 4 adjacent registers (aligned by 4, e.g. to r4, r5, r6 and r7)
8W = SETPR 2 -- Move, Load or Store 8 words into 8 adjacent registers (either all GPR or all MemPointer registers at once)
16W = SETPR 3 -- Move, Load or Store 16 words into all 16 registers, first 8 words into GPR and last 8 words into MemPointers
1B = SETPR 4 -- Load or Store 1 byte into 1 register
2B = SETPR 5 -- Load or Store 2 bytes into 2 adjacent registers (aligned to even, e.g. r0 and r1, or r6 and r7)
4B = SETPR 6 -- Load or Store 4 bytes into 4 adjacent registers (aligned by 4, e.g. to r4, r5, r6 and r7)
8B = SETPR 7 -- Load or Store 8 bytes into 8 adjacent registers (either all GPR or all MemPointer registers at once)
Byte loads and stores use least significant half of word/register.
Byte prefixes are used only for memory accesses, MOV instructions always transfer whole words (full register content)
Examples of prefix uses:
4W MOV r4 r0 -- copy registers in range r0..r3 into range r4..r7
2W LD SPH BP -- load Stack Pointer pair (SPH and SPL) with value at address stored in Base Pointer pair.
1B STob r0 SP -1 -- push one byte from register r0 to stack
Multi-word ALU operations
Provision for loading/storing and moving multiple words per instruction is complemented by extensions of ALU operations -- these just combinations of regular ALU ops that result in effective operations on data with widths bigger than 16 bit.
Following instructions can have 2-word and 4-word versions:
ADD, SUB, ADDC, SUBC, AND, ANDN, OR, ORN, XOR, XNOR, SHR, SHL, ASHR, ASHL, ROLC, RORC.
The versions are distinguished by additional letter added at the end, 'd' for operations on 32-bit values (double-word), 'l' for operations on 64-bit values (long, or quad-word).
Example:
ADDl r0 r0 r4
this is substituted with:
ADD r3 r3 r7 ADDC r2 r2 r6 ADDC r1 r1 r5 ADDC r0 r0 r4
by the Assembler.
Use of these instructions make registers appear longer, while their number drops accordingly: instead 8 16-bit registers, it looks like 4 32-bit or 2 64-bit registers.
Jump to absolute address
Regular jumps are PC-relative.
This alias makes possible jumps to absolute address in ranges 0x0000_0000 -- 0x00FF_FFFF and 0xFF00_0000 -- 0xFFFF_FFFF.
This is just an immediate load of 25-bit value into Memory Pointer Pair:
JA address == LDim PC address
Shorthand for PC-relative loads and stores
This is for loading and storing to labeled locations (static variables).
As labels (for variables) are mapped to addresses with respect to program origin, but the program itself may be loaded anywhere in memory, it is handy to provide pc-relative way to access them. This way, the offset is calculated by the assembler. Thus there is no need to have PC as part of instructions.
Here are relevant aliases:
LDo rX Label == LDo rX PC <Label - PC - 2>
STo rX Label == STo rX PC <Label - PC - 2>
The <Label - PC - 2> is calculated offset from current PC value to labeled value.
Stack operations (push and pop)
These are pre-defined loads and stores with update to the SP:
Push and pop of single register (either rX or mpX):
PUSH rX == STob rX SP -2 --- decrement SP by 2, and store value in reg rX at new address
POP rX == LDoa rX SP +2 --- load reg rX with value at address in SP, and then increment SP by 2
PUSH MP == SETPR 0; STob MPH SP -4 --- decrement SP by 4, and store value in registers MPH and MPL at new address
POP MP == SETPR 0; LDoa MPH SP +4 --- load registers MPH and MPL with value at address in SP, and then increment SP by 4
PUSH RF == SETPR 2; STob r0 SP -16 --- decrement SP by 16, and store entire Register File at new address
POP RF == SETPR 2; LDoa r0 SP +16 --- load whole Register File at once with value at address in SP, and then increment SP by 16
-
Mnemonics list
11/11/2022 at 19:15 • 0 commentsHere, mnemonics for all instructions are listed, with short descriptions:
ALU instructions (link to machine code description):
All ALU instructions perform operations only on General Purpose Registers
All ALU instructions taking 2 bytes in memory.
instructions updating one of the GPR by const value in range 0..255:
01 - ADDi rA const -- add const to value in register rA, save result to same register rA
02 - SUBi rA const -- subtract const from value in register rA, save result to same register rA
03 - XORi rA const -- bitwise XOR const with value in register rA, save result to same register rA
04 - XNORi rA const -- bitwise XOR inverted const with value in register rA, save result to same register rA
05 - ORi rA const -- bitwise OR const with value in register rA, save result to same register rA
06 - ORNi rA const -- bitwise OR inverted const with value in register rA, save result to same register rA
07 - ANDi rA const -- bitwise AND const with value in register rA, save result to same register rA
08 - ANDNi rA const -- bitwise AND inverted const with value in register rA, save result to same register rA
3-operand Arithmetic instructions
09 - ADD rY rA rB -- add value in register rB to value in register rA, and save it to register rY
10 - SUB rY rA rB -- subtract value in register rB from value in register rA, and save it to register rY
11 - ADDC rY rA rB -- add value in register rB to value in register rA, with carry, and save it to register rY
12 - SUBC rY rA rB -- subtract value in register rB to value in register rA, with borrow, and save it to register rY
3-operand Logic instructions
13 - XOR rY rA rB -- bitwise XOR value in register rB with value in register rA, and save it to register rY
14 - XORN rY rA rB -- bitwise XOR inverted value in register rB with value in register rA, and save it to register rY
15 - OR rY rA rB -- bitwise OR value in register rB with value in register rA, and save it to register rY
16 - ORN rY rA rB -- bitwise OR inverted value in register rB with value in register rA, and save it to register rY
17 - AND rY rA rB -- bitwise AND value in register rB with value in register rA, and save it to register rY
18 - ANDN rY rA rB -- bitwise AND inverted value in register rB with value in register rA, and save it to register rY
1-bit shift operations
19 - SHL rA rB -- shift value in register rB 1 bit left, save result to register rA
20 - SHR rA rB -- shift value in register rB 1 bit right, save result to register rA
21 - ROLC rA rB -- rotate value in register rB through carry 1 bit left, save result to register rA
22 - RORC rA rB -- rotate value in register rB through carry 1 bit right, save result to register rA
23 - ASHL rA rB -- arithmetic shift left value in register rB , same as regular shift, save result to register rA
24 - ASHR rA rB -- arithmetic shift right value in register rB, while preserving msb, save result to register rA
Rotations
25 - ROTi rY rA 0xF -- rotate value in register rA 0xF (0-16) bits left, save result to register rY
26 - ROT rY rA rB -- rotate value in register rA left by number of bits by value in register rB, save result to register rY
Invert
27 - INV rA rB -- flip bits in value in register rB and store result into register rA
Byte Sign Extend
28 - BSE rA rB -- copy bit 7 into bits 8..15 of the value in register rB and store result into register rA
Comparisons
29 - CMP rA rB -- Regular comparison, subtract value in register rB from value in register rA, and discard the result (only status flags are updated)
30 - CMN rA rB -- Compare Negative, add value in register rB to value in register rA, and discard the result (only status flags are updated)
31 - TST rA rB -- Test Bits, perform bitwise AND between rA and rB values, and discard the result (only status flags are updated)
32 - TEQ rA rB -- Test Equality, perform bitwise XOR between rA and rB values, and discard the result (only status flags are updated)
33 - TCM rA rB -- Test Complement, perform bitwise XNOR between rA and rB values, and discard the result (only status flags are updated)
34 - TIB rA rB -- Test Inverted Bits, perform bitwise ANDN between rA and rB values, and discard the result (only status flags are updated)
Address Arithmetic instructions (link to machine code description):
35 - ADDpi MP const -- add signed const in range -8388608..+8388607 (24-bit signed value) to address in memory pointer pair MP and store result into the same pair
36 - ADDp MP rX -- add signed value from register rX to address in memory pointer pair MP and store result into the same pair
Move instructions (link to machine code description):
The source and destination can be any of 8 GPR registers, any of 8 memory pointer registers, and any special registers in any combination except moves between two special registers and all moves from IVB -- it cannot be copied, result is undefined.
All MOV instructions taking 2 bytes in memory.
37 - MOV rA rB -- copy value stored in register rB into register rA.
38 - MOVs rA srB -- copy value stored in register srB into register rA.
Immediate Loads (link to machine code description):
All Immediate Load instructions take up 4 bytes words in memory.
39 - LDir rX 0xFFFF -- load constant in range 0..65535 into General Purpose Register rX
40 - LDim MP 0x01FFFFFF -- load constant in range 0..33554431 into Memory Pointer Pair MP. At load, the bit 25 is extended to bits 26..31, thus the address space accessible is in two ranges: 0x0000_0000..0x00FF_FFFF and 0xFF00_0000..0xFFFF_FFFF.
Direct Load and Store (link to machine code description):
The source and destination register rX can be any of 8 GPR registers and any of 8 memory pointer registers.
Direct Load and Store instructions take up 4 bytes in memory.
41 - LDd rX 0x01FFFFFF -- load 16-bit value into register rX from memory by address in ranges 0x0000_0000..0x00FF_FFFF and 0xFF00_0000..0xFFFF_FFFF.
42 - STd rX 0x01FFFFFF -- store 16-bit value from register rX into memory by address in ranges 0x0000_0000..0x00FF_FFFF and 0xFF00_0000..0xFFFF_FFFF.
Indirect Loads and Stores (link to machine code description):
The source or destination register rY can be any of 8 GPR registers and any of 8 memory pointer registers.
The base address (MP) is in one of the Memory Pointer Pairs (MP).
Offset can be a) explicit value or b) value in one of the General Purpose Registers rX; offset is signed 16-bit value (range -32768..+32767).
Load and Store with no offset:
These instructions take up 2 bytes in memory.
43 - LD rY MP -- load 16-bit value into register rX from memory by address in MP
44 - ST rY MP -- store 16-bit value into register rX from memory by address in MP
Load and Store with explicit offset:
These instructions take up 4 bytes in memory.
45 - LDo rY MP 0xFFFF -- load 16-bit value into register rY from memory by address offset from MP by explicit value
46 - STo rY MP 0xFFFF -- store 16-bit value from register rY into memory by address offset from MP by explicit value
With post-increment:
47 - LDoa rY MP 0xFFFF -- load 16-bit value into register rY from memory by address offset in MP, then add explicit value to MP and store result in MPWith pre-increment
48 - SToa rY MP 0xFFFF -- store 16-bit value into register rY from memory by address offset in MP, then add explicit value to MP and store result in MP
With pre-increment
49 - LDob rY MP 0xFFFF -- load 16-bit value into register rY from memory by address offset from MP by explicit value, store new address in MP
50 - STob rY MP 0xFFFF -- store 16-bit value into register rY from memory by address offset from MP by explicit value, store new address in MP
Load and Store with offset in register:
These instructions take up 2 bytes in memory.
51 - LDr rY MP rX -- load 16-bit value into register rY from memory by address offset from MP by value in rX
52 - STr rY MP rX -- store 16-bit value from register rY into memory by address offset from MP by value in rX
With post-increment:
53 - LDra rY MP rX -- load 16-bit value into register rY from memory by address offset in MP, then add value in rX to MP and store result in MP
54 - STra rY MP rX -- store 16-bit value into register rY from memory by address offset in MP, then add value in rX to MP and store result in MP
With pre-increment
55 - LDrb rY MP rX -- load 16-bit value into register rY from memory by address offset from MP by value in rX, store new address in MP
56 - STrb rY MP rX -- store 16-bit value into register rY from memory by address offset from MP by value in rX, store new address in MP
Jump instructions (link to machine code description):
Jumps are instructions that update the first Memory Pointer Register pair (Program Counter). The new value is calculated somewhat like in Address Arithmetic instructions, the difference being that PC is implicit destination, while the base address can be in any of 4 Memory Pointer Pairs, and the calculation is conditional (for conditional jumps). If base address is in PC, jumps become PC-relative, and thus code is position-independent.
The offset values are 16-bit signed values, in can be from one of General Purpose Registers or from explicit immediate value.
All Jump instructions take up 4 bytes in memory.
57 - J 0xFFFFFF -- unconditionally load PC with sum of value in MP register pair and signed 24-bit value
58 - JZ 0xFFFFFF -- if Zero flag is "1" load PC with sum of value in MP register pair and signed 24-bit value
59 - JN 0xFFFFFF -- if Negative flag is "1" load PC with sum of value in MP register pair and signed 24-bit value
60 - JO 0xFFFFFF -- if Overflow flag is "1" load PC with sum of value in MP register pair and signed 24-bit value
61 - JC 0xFFFFFF -- if Carry flag is "1" load PC with sum of value in MP register pair and signed 24-bit value
62 - JNZ 0xFFFFFF -- if Zero flag is "0" load PC with sum of value in MP register pair and signed 24-bit value
63 - JNN 0xFFFFFF -- if Negative flag is "0" load PC with sum of value in MP register pair and signed 24-bit value
64 - JNO 0xFFFFFF -- if Overflow flag is "0" load PC with sum of value in MP register pair and signed 24-bit value
65 - JNC 0xFFFFFF -- if Carry flag is "0" load PC with sum of value in MP register pair and signed 24-bit value
66 - JSR 0xFFFFFF -- unconditionally store current value of PC to memory at address in SP - 4, then load PC with sum of current PC value and signed 24-bit value
Miscellaneous instructions (link to machine code description):
These are assorted service-type instructions outside of above categorization
All these instructions take up 2 bytes in memory.
67 - SETIM M -- Set interrupt mask, M is number in range 0..7
68 - CLRIM M -- Clear interrupt mask, M is number in range 0..7
69 - SETPR P -- Set prefix, P is number in range 0..7
70 - EINT I -- Enter interrupt service routine, I is number in range 0..255
71 - DMA -- Direct memory access - set address selector to '0b11', stop propagation of clock signal into processor
72 - RESET -- software cpu reset - clear all registers
73 - HLT -- halt execution - stop propagation of clock signal into processor
74 - NOP -- empty operation, advance PC by 2 bytes.