My dream CPU

III. Assembler.

ADDRESSING METHODS

RCPU have only 3 addressing methods: direct, absolute, index addressing.

Direct addressing

With this addressing method the number in operand will be assign to any of registers in the CPU. With this addressing kind we can assign direct value in register from integer unit, floating point unit and addressing unit. The instruction length is 2 consecutive addresses in memory, for floating point unit in 3 consecutive addresses.

Example:
I: rA <-- #56 // rA from integer unit will be loaded with 56
D: rA <-- #3.14 // rA from floating point unite will be loaded with 3.14

Absolute addressing

In this method the instruction operand is one address, which will be read its value and will be assign to any register in CPU, or back, address in which will be written value from any register. When data flow is from CPU to memory data source could be not a register, could be result from arithmetic or logical calculation. Instruction length is 2 consecutive addresses.

Example:
I: rB <-- M[, ]500 // rB in integer unit will be loaded from address 500

D: rA --> M[, ]600 // rA from float unit will be stored in address 600 and 601

Index addressing

In this kind addressing the address in which will read or write is calculated from sum between base and index register plus instruction operand value. It is possible only index or base value plus instruction operand value.

Example:
I: rA <-- M[rBs1, rX2]5
// rA in integer unit will be loaded from address [rBs1 + rX2 + 5]

D: rA --> M[, rX3]0
// rA in floating point unit will be written in address. [rX3 + 0]. In address pointed from rX3.





RCPU INSTRUCTIONS

The instruction contain operation code and operand on the next address.

Fig. 7 Instruction format.



operation code contain:

1. Instruction Unit ( pipeline ):
I - Integer;
D - Floating point;
A – Address.

In assembler „ : “ is delimiter between the pipeline and register for readability.

2. Direction for data transfer - memory-CPU, CPU-memory, register-register. The arrow shows the direction.

3. Register about the instruction is. In wich will be written or read from it. About I: and D: this are rA and rB. About A: are rBs1, rBs2, rBs3, rX1, rX2, rX3, rMaxX, IP, SP. When data transfer is from CPU to memory are possible the following comands, wich result will be stored in memory:
arithmetic: AplsB, AmnsB, BmnsA, AmulB, AdivB, BdivA, sortAB
logical: AandB, AorB, AxorB, AshlB, AshrB, AshrrB

4. Base and or index register to calc address. This are: rBs1, rBs2, rBs3, rX1, rX2, rX3
Examples:

.....M[rBs1, rX1]10 // Address = rBs1 + rX1 + 10
….M[rBs2, ]5 // Address = rBs2 + 10
….M[, rX3]0 // Address = rX3
….M[rBs2, rX1]15 // Address = rBs2 + rX1 + 15
….M[]255 // Address = 255 // absolute addressing


Instruction list for Integer pipeline

Load registers rA и rB.

I: rA <-- M[] - load register rA
I: rB <-- M[] - load register rB
I: rB <-- # - load register rB

The arrow is from memory to register.
With this instructions is possible direct, index and absolute addressing.

Examples:

I: rA <-- #5     - load rA with 5. Direct addressing.

I: rA <-- M[rBs1, rX1]10     - load rA from memory address calc thru rBs1 + rX1 + 10. Index addressing.

I: rB <-- M[]500     - load rB from address 500. Absolute addressing.

With sign „ # “ denote direct addressing. With „ M “ memory is used for absolute and index addressing. When between the bracets thera are not registers this is absolute addressing, if there are registers this is index addressing.
Store registers in memory:

I: rA --> M[, ] - store rA

I: rB --> M[, ] - store rB

Example:

I: rA --> M[, ]500 - store rA in address 500.

I: rB --> M[, rX3]0 - store rB in address pointed from rX3

Arithmetic operations:

AplsB     // rA + rB

AmnsB     // rA - rB

BmnsA     // rB- rA

AmulB     // rA * rB

AdivB     // rA / rB

BdivA     // rB / rA


Examples:

I: AplsB --> M[, rX1]3
The result from calc rA + rB will be stored at address pointed from rX1+3

I: BdivA --> M550
The result from calc rB /rA will be stored at address 550


logical operations:
AandB - logical AND
AorB - logical OR
AxorB - logical XOR
AshlB - SHL, shift left rA thru bits in rB
AshrB - SHR, shift right in rA thru bits in rB
AshrrB - SHR, shift right in rA with sign thru bits in rB

With 32 bit release are used only 5 right bits from rB
With 64 bit release are used only 6 right bits from rB
Examples:

I: AandB --> M[rBs3, rX3]
// The calc result from rA and rB will be stored at address pointed from rBs3 +rX3

Branch Instructions:

ifAB - Compare registers rA and rB with any condition < , <=, =>, >, ==
Will be branch if condition is true. Branch could be done on address thru absolute or index addressing.
Example:

I: if ( A > B ) jump M1000 // If rA > rB branch in address 1000.

sortAB - Sort rA and rB. Exchange register values by condition < or >. Branch if: if Exchange – rA and rB war exchanged.
if NOT - (if NOT Exchange ) rA and rB war NOT exchanged.
Could be used absolute or index addressing.
Examples:

I: SortAB > ; IfExch M1200
// After instruction execution rA value will be bigger than rB. If there was exchange will be branch on address 1200.

I: SortAB > ; IfNoExch M1300
// After instruction execution rA value will be bigger than rB. If there was NOT exchange will be branch on address 1300. Usualy if there is not exchange will be jump over next 2 instructions, wich store rA and rB back in memory. Store back in memory is not needed when they are in natural sort order. This is faster sort.
Stack Instructions:
Push - store register in stack
pop - load register from stack

Examples:
I: push rA // Store value from rA in stack and decrease SP with 1

I: pop rB // load rB from stack top, inc SP with 1.

Floating point unit Instruction list

Instructions are the same as for Integer Unit. Logical operations are missing. Stack instructions increase or decrease SP with 2, becouse floating numbers are stored in 2 addresses. The examples are the same, just replace I: with D:

Address Unit Instruction list

Instructions memory --> register:
A: rBs1 <-- M // load register rBs1
A: rBs2 <-- M // load register rBs2
A: rBs3 <-- M // load register rBs3

A: rX1 <-- M // load register rX1
A: rX2 <-- M // load register rX2
A: rX3 <-- M // load register rX3
A: rIP <-- M // load register rIP; Equal to no condition jump
A: rSP <-- M // load register rSP; Recommended to use it only in the beginning, CPU establishment.
A: rMaxX <-- M //load register rMaxX

With all this instructions could be used direct, absolute and index addressing.

Instructions register – memory, are the same as memory-register, just the arrow is in back sign. Direct addressing is not possible.
Branch Instructions:
A: IfMaxX rX1 < rMaxX ; M
// If rX1 < rMaxX will be a branch on address. Can be used registers rX1, rX2, rX3. Absolute addressing.

Increment:
A: IncX rX2 M
// Increment register rX2. Possible with registers rX1, rX2, rX3. Direct and absolute addressing.
Stack instructions:
A: push rX1
// Store in stack value from rX1. Could be used all registers from Address Unit without SP.

A: pop rX1
// Load from stack rX1. Could be used all registers from Address Unit without SP.

A: pushCi   // Store Integer constant in stack.

A: pushCd   // Store Floating number constant in stack.

Last 2 Instructions pushCi and pushCd are in group instructions for Address Unit because they change value only in SP and ofcourse stored value in stack. They don't change register in another unit.
Instructions register-register

The Instructions register-register are possible between registers in the same unit and between registers in different units. With Instructions with source Integer unit or Address unit and destination Floating point unit its float part will be 0. With Instructions with source Floating point unit and destination Integer unit or Address unit, fraction part is ignored.

Register - register in Integer unit:

In this instruction group are instructions for value transfer between rA and rB and store calc result in register.
Value transfer.
I: rA --> I: rB // Value from rA is stored in rB
I: rB --> I: rA // Value from rB is stored in rA

Assign calc result to register.
I: AplsB --> I: rA // rA + rB assign to rA

Possible are all valid operations in Integer unit.
AplsB, AmnsB, BmnsA, AmulB, AdivB, BdivA, AandB, AorB, AxorB, AshlB, AshrB, AshrrB

I: AplsB --> I: rA
I: AmnsB --> I: rA
I: BmnsA --> I: rA
I: AmulB --> I: rA
I: AdivB --> I: rA
I: BdivA --> I: rA
I: AandB --> I: rA
I: AorB --> I: rA
I: AxorB --> I: rA
I: AshlB --> I: rA
I: AshrB --> I: rA
I: AshrrB --> I: rA

Result can be assign to rB to.

Register - register in Floating point unit:

The Instructions are the same as in Integer unit, just replace I: with D:

Register - register in Address unit:

This Instructions are for sending value in Address unit. Should be carefull when set IP, this is equal to jump instruction. Be carefull set value in SP. Read from IP and SP is not a problem.

It is possible between all registers in Address unit.
rBs1, rBs2, rBs3, rX1, rX2, rX3, rMaxX, IP, SP

A: rBs1 --> A: rX2
A: rBs2 --> A: rX2
A: rBs3 --> A: rX2
A: rX1 --> A: rX2
A: rX2 --> A: rX2 // yes it is possible, but not helpfull
A: rX3 --> A: rX2
A: rMaxX --> A: rX2
A: IP --> A: rX2
A: SP --> A: rX2

Integer unit – Address unit:

Possible between all registers from integer unit and address unit.

Examples:

I: rA --> A: rX1

It is possible calc result from Integer unit to be assign to register in Address unit.

Example:
I: AplsB --> A: rX2 // rA + rB assign to rX2
All registers and operations in Integer unit and Address unit are valid.

Address unit - Integer unit:

A: rX1 --> I: rA // rA in Integer unit assept value from rX1 Adress unit.

It is possible to use evey one from register from Address unit ( rBs1, rBs2, rBs3, rX1, rX2, rX3, rMaxX, IP, SP ) and rA and rB from Integer unit.

Floating point unit - Address unit:

D: rA --> A: rX1 // Integer part from rA will be assign to rX1

It is possible calc result from floating point unit to be assign to register from Address unit.

Example:
D: AmulB --> A: rMaxX // Integer part from rA * rB will be assign to rMaxX in Address unit.

Every from registers (rA, rB) or calc result in Floating point unit ( AplsB, AmnsB, BmnsA, AmulB, AdivB, BdivA ) can be assign to register in Address unit ( rBs1, rBs2, rBs3, rX1, rX2, rX3, rMaxX, IP, SP ) fraction part is ignored.

Address unit - Floating point unit:

The value from every register from Address unit ( rBs1, rBs2, rBs3, rX1, rX2, rX3, rMaxX, IP, SP ) can be assign to any of rA or rB, fraction part is ignored.
Examples:

A: rBs1 --> D: rB // rB from Floating point unit will accept value from rBs1 from Address unit.

Integer unit – Floating point unit:

Every register ( rA, rB ) or calc result ( AplsB, AmnsB, BmnsA, AmulB, AdivB, BdivA, AandB, AorB, AxorB, AshlB, AshrB, AshrrB ) in Integer unit can be assign to register rA or rB from Floating point unit, fraction part is ignored.
Example:

I: AdivB --> D: rA // Calc result from rA/rB in Integer unit will be assign to register rA in Floating point unit.

Floating point unit - Integer unit:

Value from rA or rB from Floating point unit or its calc result (AplsB, AmnsB, BmnsA, AmulB, AdivB, BdivA,) can be assign to register rA or rB in Integer unit. Integer part only.
Example:

D: AmnsB --> I: rA // Integer part from calc rA – rB from Floating point unit will be assign to register rA from Integer unit.

Some special instructions

Instructions which set value to Instruction pointer IP have some peculiarity. This is equal to jump instruction. When this instruction is in 2 stage on instruction pipeline, after its execution 1-st stage is reset, to avoid instruction execution after it.