Opcodes and Operands
- Opcode: unique value indicating an operation
- Operand: opcode dependent
→ Could be a register, addressing mode, address, or offset
- An instruction needs space for its opcode, operands, and any addressing modes
- Must be wide enough to support
→ arithmetic ops
→ memory addressing
→ branching
→ other speciaized instructions
- lengths can be fixed or variable
- Two approaches to registers:
→ Accumulators and index registers (specialized)
⇒ accumulators: arithmetic and logic
⇒ index: indexing/addressing (arrays)
→ General purpose
⇒ Can do everything.
- Depending on the number of registers you have, the number of bits regquired to encode them increases.
→ e.g. 16 registers requires 4 bits
- If each memory location is N-bits wide, how can an N-bit address fit in an N-bit instruction?
→ Fixed length instructions must include only part of the address or data
⇒ pro: one fetch, one instruction
⇒ standardize internal structure
⇒ handling addresses and accessing data can cause problems. Always need the opcode in the instruction, so we always have to get words in two steps.
→ Variable length instructions can use multiple memory locations... they can hold the entire 16 bits of data or address.
⇒ Machine would have to support single or multiple word instruction fetches
⇒ This makes the machine more complex
⇒ There are ways of getting around this:
• You can fetch the 16 bit instruction, and then it will get decoded
• The next location (PC + 2) (sometimes referred to as PC relative) will hold the data.
• The execute stage would get the memory at the program counter, and the PC has to be incremented again to get the next instruction. Because the DATA is at the location where the PC currently is.
⇒ Potentially a wider number of address and data structures
⇒ number of memory accesses varies by instruction
- Once the instruction has an immediate value in it, we can't easily change it. However, if the value is in a memory location, we can change the memory location. The trouble with immediates, the value is essentially constant
-
Number of Operands
Zero operands
- just the opcode with no operands
- referred to as an implicit operation
- implied effective address or register
→ PSW instructions e.g. CLRC, SETC
⇒ ACC or IX: increment ACC or IX
- Stack machine
→ arithmetic operations between the top two stack values.
- Polish notation:
→ data values followed by the operation
⇒ D1 D2 +
⇒ (a + b) * c → a b + c *
- Motorola 6811:
→ had two accumulators, both 8 bits, A and B
→ there was an instruction INCB that would increment accumulator B
→ These were called inherent (INH) instructions aka zero operands
→ INS incremented stack, INX incremented register x... etc
→ DES decremented stack, DEX decremented register x...
→ We can do this with ADD #1 Rx... but we take 16 bits to do it. Motorola did it in 8 for these specific registers.
→ They took up too many locations with all the inherent instructions so they did something else, they gave each inherent instruction a prefix
→ Then on fetch, if the IR was equal to the constant, e.g. 0x18 for IY, then it would perform another fetch and signal that it was an IY instruction.
→ We can do this with ADD #1 Rx... but we take 16 bits to do it. Motorola did it in 8
CONTINUED 2023/07/04 - 12:17
- If you have a zero-address machine, when you come across an instruction such as ADD, the assumption is that the SRC and DST are the top two items on the stack. Then the TOS becomes the result of the addition.
- If we have a one-address machine, it would be <ADD operand>. the implication is that you would have an accumulator, a dedicated register to which all arithmetic operations take place.
- ADDA MEM_LOC → ACCA ← ACCA + MEM[MEM_LOC]
- A two-address machine would look like ADD R1, R2 where r1 is the src and r2 is the dst
- DST ← DST + SRC
- You could have a 2-address machine where it would be like ADD R0, MEM_LOC R0 ← R0 + MEM[MEM_LOC]
- In our case the effective address is always a register, in some machines it could be a memory location.
One operand
[opcode][operand]
- EA: effective address
→ obtained from the oeprand (register + addressing mode)
→ Operation on a single register, e.g. clear a register.
→ If it's a branch instruction, it cannot hold the full address. It has to be an offset.
- one operand machines:
→ We can do the same thing with a MOVLZ or whatever
→ EA obtained from the operand
→ implied register (e.g. accumulator or index register)
⇒ LDAA #5 ← implied second operand (accumulator a). Effective Address is embedded in the instruction
⇒ STAB Result ← implied register here is accumulator B (store accumulator B in Result mem location) Mem[Result] ← Accumulator B
- One-op instructions on Morotola 6811
→ IMM (immediate)
⇒ 8bit data follows instruction
→ DIR
⇒ Direct addressing
⇒ takes an 8-bit data value
⇒ Low memory (0000 to 00FF)
⇒ LSByte follows
⇒ CPU concatenates MSByte (00)
⇒ How do we access 0100 to FFFF?
→ EXT
⇒ extended addressing
⇒ LDAA then MS then LS
• stored big endian
⇒ If you only have a limited amount of memory you can put all your data in the first 256 bits and then the rest of your code can access that memory with direct addressing.
Two Operands
- Interpretation depends on the machine's ISA
- ACC and IXs:
→ Relative addressing
⇒ EA ← Op1 + op2
⇒ ACC ← memory[EA]
- General purpose
→ EA1 ← Addressing mode of OP1
→ EA2 ← Addressing mode of OP2
→ depends on opcode
Fixed and Variable width instructions
Index