The next phase in the instruction execution cycle is to decode the assembler instruction.
Decoding means: find out what the assembler instruction means
Various motivations of differing importance will dictate the design, such as: fixed vs. variable length, how many registers does the CPU have, what can each register do, etc.
We will use a very simple-minded assembler code to illutsrate the CPU. Also, a simple assembler code will simplify the decoding process.
| Instruction code | Mnemonic | Instruction | Meaning |
|---|---|---|---|
| 0000xxxxxxxxxxxx | LODD | Load Direct | ac <- mem[x] |
| 0001xxxxxxxxxxxx | STOD | Store Direct | mem[x] <- mem[x] |
| 0010xxxxxxxxxxxx | ADDD | Add Direct | ac <- ac + mem[x] |
| 0011xxxxxxxxxxxx | SUBD | Subtract Direct | ac <- ac - mem[x] |
| 0100xxxxxxxxxxxx | JPOS | Jump positive | if ac > 0 then pc <- x |
| 0101xxxxxxxxxxxx | JZER | Jump zero | if ac = 0 then pc <- x |
| 0110xxxxxxxxxxxx | JUMP | Jump always | pc <- x |
| 0111xxxxxxxxxxxx | LODC | Load constant | ac <- x |
| 1000xxxxxxxxxxxx | LODL | Load local | ac <- mem[sp + x] |
| 1001xxxxxxxxxxxx | STOL | Store local | mem[sp + x] <- ac |
| 1010xxxxxxxxxxxx | ADDL | Add local | ac = ac + mem[sp + x] |
| 1011xxxxxxxxxxxx | SUBL | Subtract local | ac = ac - mem[sp + x] |
| 1100xxxxxxxxxxxx | JNEG | Jump negative | if ac < 0 then pc <- x |
| 1101xxxxxxxxxxxx | JNZE | Jump nonzero | if ac != 0 then pc <- x |
| 1110xxxxxxxxxxxx | CALL | Call subroutine | sp <- sp-1; mem[sp] <- pc; pc <- x |
| 1111000000000000 | PUSHI | Push Indirect | sp <- sp-1; mem[sp] <- mem[ac] |
| 1111000100000000 | POPI | Pop Indirect | mem[ac] <- mem[sp]; sp <- sp+1; |
| 1111001000000000 | PUSH | Push on stack | sp <- sp-1; mem[sp] <- ac |
| 1111010000000000 | POP | Pop off stack | ac <- mem[sp]; sp <- sp+1; |
| 1111100000000000 | RET | Return from subroutine | pc <- mem[sp]; sp <- sp+1; |
| 1111101000000000 | SWAP | Swap ac and sp | tmp <- ac; ac <- sp; sp <- tmp |
| 11111100yyyyyyyy | INCSP | Increment sp | sp <- sp + y |
| 11111110yyyyyyyy | DECSP | Decrement sp | sp <- sp - y |
Example 1:
If assembler instruction read in is: 0000000000001111 According to the encoding in the table above, this assembler instruction means: Load (the first bits are 0000 which means "load") the data from memory address 000000001111 into the AC (accumulator) register We have seen how the CPU can instruct the datapath to load data from memory using the following micro-instructions (click here): 1. mar = 0000000000001111; rd; // Send out addr and read request 2. rd; // Use 0 of more of this instr to wait 3. rd; mbr; // When data is read on databus, read into MBR 4. ac := mbr; // Transfer data from MBR to destinationThe webpage at (click here) contains picture that shows the dataflow in these instruction.
Example 2:
If assembler instruction read in is: 0001000000001111 According to the encoding in the table above, this assembler instruction means: Write (the first bits are 0001 which means "Store") the data from the AC register to memory address 000000001111 We have also seen how the CPU can instruct the datapath to write data from memory using the following micro-instructions (click here): 1. mar = 0000000000001111; mbr = ac; wr; // Send out addr in MAR, the data in MBR and a write request. 2. wr; // Use 0 of more of this instr to wait for the memory // to finishThe webpage at (click here) contains picture that shows the dataflow in these instruction.
START:
// Fetch next assembler instruction from memory at address "PC"
// (has been discussed)
// Now we decode the assembler instruction:
if ( left most bit in assembler code == 0 )
{ // This program segment decodes assembler instructions 0???.....
if ( 2nd left most bit in assembler code == 0 )
{ // This program segment decodes 00??.....
if ( 3rd left most bit in assembler code == 0 )
{ // This program segment decodes 000?.....
if ( 4th left most bit in assembler code == 0 )
{ // Jackpot: 0000xxxxxxxxxxxx is a load operation
mar = addr "xxxxxxxxxxxx" in assemler instruction; rd;
// Send out addr and read request
rd; mbr; // Read databus into MBR
ac := mbr; goto START; // Transfer data from MBR to destination
// and loop back (fetch next assm instr)
}
else
{ // Jackpot: 0001xxxxxxxxxxxx is a store operation
mar = addr "xxxxxxxxxxxx"; mbr = ac; wr;
// Send out addr in MAR, the data in MBR
// and a write request.
wr; goto START; // Wait for memory to finish and then
// loop back (fetch next assm instr)
}
else
{ // This program segment decodes 001?.....
...
}
}
else
{ // This program segment decodes 01??.....
...
}
}
else
{ // This program segment decodes assembler instructions 1???.....
...
... (similar construction as above)
}
ADDR Micro Assembler Instruction Comment
===========================================================================
0: mar := pc; rd;
1: pc := pc + 1; rd; mbr; // Fetch assembler instruction
2: ir := mbr; if n then goto 31; // Test left most bit
3: tir := lshift(ir + ir); if n then goto 22; // Test 2nd left most bit
4: tir := lshift(tir); if n then goto 13; // Test 3rd left most bit
5: alu := tir; if n then goto 9; // Test 4th left most bit
6: mar := ir; rd; // Micro-program instructions that read
7: rd; mbr; // data at address given in the assembler instr
8: ac := mbr; goto 0; // into AC register (and loop back to START)
9: ir := ir and r8; // Micro-program instructions that write
10: mar := ir; mbr := ac; wr; // data from AC register to memory at address
11: wr; goto 0; // given in the assembler instr & loop back
12: alu := tir; if n then goto 17; {0010 or 0011?}
....
As you have seen, this is the code for the assembler instruction move the word at memory location 15 to the AC register
Note: if you were to program in assembler, you may have written something like "move 15, AC" and the assembler will translate this "text" representation into the assembler code 0000000000001111
So after the micro-program instructions
0: mar := pc; rd;
1: pc := pc + 1; rd; mbr;
The MBR contains 0000000000001111.
2: ir := mbr; if n then goto 31;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // Address 3: program segment decodes assembler instructions 0???.....
}
else
{ // Address 31: program segment decodes assembler instructions 1???.....
}
Pictorially:
3: tir := lshift(ir + ir); if n then goto 22;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // This program segment decodes assembler instructions 0???.....
if ( 2nd left most bit in assembler code == 0 )
{ // Address 4: program segment decodes 00??.....
}
else
{ // Address 22: program segment decodes 01??.....
}
Pictorially:
Therefore:
4: tir := lshift(tir); if n then goto 13;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // This program segment decodes assembler instructions 0???.....
if ( 2nd left most bit in assembler code == 0 )
{ // Address 4: program segment decodes 00??.....
}
if ( 3rd left most bit in assembler code == 0 )
{ // Address 5: program segment decodes 000??.....
}
else
{ // Address 13: program segment decodes 001??.....
}
....
Pictorially:
Therefore:
5: alu := tir; if n then goto 9;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // This program segment decodes assembler instructions 0???.....
if ( 2nd left most bit in assembler code == 0 )
{ // Address 4: program segment decodes 00??.....
}
if ( 3rd left most bit in assembler code == 0 )
{ // Address 5: program segment decodes 000??.....
if ( 3rd left most bit in assembler code == 0 )
{ // Address 6: program segment handles 0000xxxxx...
}
else
{ // Address 9: program segment handles 0001xxxxx...
}
}
....
Pictorially:
Therefore:
The only way that the micro-program reaches the micro-instruction at MPC=6 is when the first 4 bits of the assembler code is 0000.... We know that the assembler instruction is a "load" (read) instruction !
We now enter the next phases of the instruction execution cycle: (3) fetch operand and (4) execute the assembler instruction.
The program segment that starts at address 6 will instruct the datapath to perform the "load" (read) operation. Let's look at it more carefully next...
6: mar := ir; rd;
Pictorially:
Therefore:
7: rd; mbr;
Pictorially:
Result:
8: ac := mbr; goto 0;
Pictorially:
Result:
Notice that MPC = 0 now, and you have seen the micro-instruction at address 0 before: it fetches an assembler code from memory location at address given by the PC register. Since PC has been updated to point to the next assembler instruction, the CPU will now fetch and execute the next assembler instruction and the instruction execution cycle is complete (indeed, the CPU has just read the data from memory location 15 into the AC register as specified by the assembler instruction 0000000000001111.... and it moves on to fetch the next assembler instruction (and then decode it and execute it...)
Do the following:
As you know, this is the code for the assembler instruction that moves the word in the AC register to memory location 15.
Note: if you were to program in assembler, you may have written something like "move AC, 15" and the assembler will translate this "text" representation into the assembler code 0001000000001111
So we consider the case that this assembler instruction is fetched by phase 1 of the instruction execution cycle. After:
0: mar := pc; rd;
1: pc := pc + 1; rd; mbr;
the MBR contains 0001000000001111.
2: ir := mbr; if n then goto 31;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // Address 3: program segment decodes assembler instructions 0???.....
}
else
{ // Address 31: program segment decodes assembler instructions 1???.....
}
Pictorially:
3: tir := lshift(ir + ir); if n then goto 22;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // This program segment decodes assembler instructions 0???.....
if ( 2nd left most bit in assembler code == 0 )
{ // Address 4: program segment decodes 00??.....
}
else
{ // Address 22: program segment decodes 01??.....
}
Pictorially:
Therefore:
4: tir := lshift(tir); if n then goto 13;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // This program segment decodes assembler instructions 0???.....
if ( 2nd left most bit in assembler code == 0 )
{ // Address 4: program segment decodes 00??.....
}
if ( 3rd left most bit in assembler code == 0 )
{ // Address 5: program segment decodes 000??.....
}
else
{ // Address 13: program segment decodes 001??.....
}
....
Pictorially:
Therefore:
5: alu := tir; if n then goto 9;
This micro-instruction forms the following if-construct:
if ( left most bit in assembler code == 0 )
{ // This program segment decodes assembler instructions 0???.....
if ( 2nd left most bit in assembler code == 0 )
{ // Address 4: program segment decodes 00??.....
}
if ( 3rd left most bit in assembler code == 0 )
{ // Address 5: program segment decodes 000??.....
if ( 3rd left most bit in assembler code == 0 )
{ // Address 6: program segment handles 0000xxxxx...
}
else
{ // Address 9: program segment handles 0001xxxxx...
}
}
....
Pictorially:
Therefore:
The only way that the micro-program reaches the micro-instruction at MPC=9 is when the first 4 bits of the assembler code is 0001.... We know that the assembler instruction is a "store" (write) instruction !
We now enter the next phases of the instruction execution cycle: (3) fetch operand and (4) execute the assembler instruction.
The program segment that starts at address 9 will instruct the datapath to perform the "store" (write) operation. Let's look at it more carefully next...
9: ir := ir and r8;
Pictorially:
Therefore:
10: mar := ir; mbr := ac; wr;
Pictorially:
Result:
11: wr; goto 0;
Pictorially:
Result:
Again, notice that MPC = 0 now, and you have seen the micro-instruction at address 0 before: it fetches an assembler code from memory location at address given by the PC register. Since PC has been updated to point to the next assembler instruction, the CPU will now fetch and execute the next assembler instruction and the instruction execution cycle is complete (indeed, the CPU has just written AC to memory location 15 as specified by the assembler instruction 0001000000001111....
Do the following: