Mips Isa
Mips Isa
Martha A. Kim
Columbia University
Spring 2016
1 / 67
Instruction Set
Architectures
MIPS Higher-Level Constructs
The GCD Algorithm Expressions
MIPS Registers Conditionals
Types of Instructions Loops
Computational Arrays
Load and Store Strings & Hello World
Jump and Branch ASCII
Other Subroutines
Instruction Encoding Towers of Hanoi Example
Register-type Factorial Example
Immediate-type Memory Layout
Jump-type Differences in Other ISAs
Assembler
Pseudoinstructions
2 / 67
So, Where Are We?
3 / 67
The Rest of the Semester: The Big Picture
Software
Hardware
4 / 67
The Rest of the Semester: The Big Picture
Software
4 / 67
The Rest of the Semester: The Big Picture
Software
Processor (CPU)
4 / 67
The Rest of the Semester: The Big Picture
Software
Processor (CPU)
Processor (CPU)
Processor (CPU)
Processor (CPU)
4 / 67
C → Assembly → Machine Code
5 / 67
Algorithms
al·go·rithm
Merriam-Webster
6 / 67
The Stored-Program Computer
John von Neumann, First Draft of a Report on the EDVAC,
1945.
8 / 67
Architecture vs. Microarchitecture
Architecture:
The interface the
hardware
presents to the
software
Microarchitecture:
The detailed
implemention of
the architecture
9 / 67
MIPS
Microprocessor without Interlocked Pipeline Stages
MIPS developed at Stanford by Hennessey et al.
MIPS Computer Systems founded 1984. SGI acquired
MIPS in 1992; spun it out in 1998 as MIPS Technologies.
10 / 67
RISC vs. CISC Architectures
11 / 67
The GCD Algorithm
12 / 67
The GCD Algorithm
13 / 67
Euclid’s Algorithm in MIPS Assembly
gcd:
beq $a0, $a1, .L2 # if a = b, go to exit
sgt $v0, $a1, $a0 # Is b > a?
bne $v0, $zero, .L1 # Yes, goto .L1
.L1:
subu $a1, $a1, $a0 # Subtract a from b (a < b)
b gcd # and repeat
.L2:
move $v0, $a0 # return a
jr $ra # Return to caller
Opcodes
14 / 67
Euclid’s Algorithm in MIPS Assembly
gcd:
beq $a0, $a1, .L2 # if a = b, go to exit
sgt $v0, $a1, $a0 # Is b > a?
bne $v0, $zero, .L1 # Yes, goto .L1
.L1:
subu $a1, $a1, $a0 # Subtract a from b (a < b)
b gcd # and repeat
.L2:
move $v0, $a0 # return a
jr $ra # Return to caller
Operands: Registers, etc.
14 / 67
Euclid’s Algorithm in MIPS Assembly
gcd:
beq $a0, $a1, .L2 # if a = b, go to exit
sgt $v0, $a1, $a0 # Is b > a?
bne $v0, $zero, .L1 # Yes, goto .L1
.L1:
subu $a1, $a1, $a0 # Subtract a from b (a < b)
b gcd # and repeat
.L2:
move $v0, $a0 # return a
jr $ra # Return to caller
Labels
14 / 67
Euclid’s Algorithm in MIPS Assembly
gcd:
beq $a0, $a1, .L2 # if a = b, go to exit
sgt $v0, $a1, $a0 # Is b > a?
bne $v0, $zero, .L1 # Yes, goto .L1
.L1:
subu $a1, $a1, $a0 # Subtract a from b (a < b)
b gcd # and repeat
.L2:
move $v0, $a0 # return a
jr $ra # Return to caller
Comments
14 / 67
Euclid’s Algorithm in MIPS Assembly
gcd:
beq $a0, $a1, .L2 # if a = b, go to exit
sgt $v0, $a1, $a0 # Is b > a?
bne $v0, $zero, .L1 # Yes, goto .L1
.L1:
subu $a1, $a1, $a0 # Subtract a from b (a < b)
b gcd # and repeat
.L2:
move $v0, $a0 # return a
jr $ra # Return to caller
Arithmetic Instructions
14 / 67
Euclid’s Algorithm in MIPS Assembly
gcd:
beq $a0, $a1, .L2 # if a = b, go to exit
sgt $v0, $a1, $a0 # Is b > a?
bne $v0, $zero, .L1 # Yes, goto .L1
.L1:
subu $a1, $a1, $a0 # Subtract a from b (a < b)
b gcd # and repeat
.L2:
move $v0, $a0 # return a
jr $ra # Return to caller
Control-transfer instructions
14 / 67
General-Purpose Registers
Name Number Usage Preserved?
$zero 0 Constant zero
$at 1 Reserved (assembler)
$v0–$v1 2–3 Function result
$a0–$a3 4–7 Function arguments
$t0–$t7 8–15 Temporaries
$s0–$s7 16–23 Saved yes
$t8–$t9 24–25 Temporaries
$k0–$k1 26-27 Reserved (OS)
$gp 28 Global pointer yes
$sp 29 Stack pointer yes
$fp 30 Frame pointer yes
$ra 31 Return address yes
15 / 67
Types of Instructions
16 / 67
Computational Instructions
Arithmetic Shift Instructions
add Add sll Shift left logical
addu Add unsigned srl Shift right logical
sub Subtract sra Shift right arithmetic
subu Subtract unsigned sllv Shift left logical variable
slt Set on less than srlv Shift right logical variable
sltu Set on less than unsigned srav Shift right arith. variable
and AND
Multiply/Divide
or OR
xor Exclusive OR mult Multiply
nor NOR multu Multiply unsigned
div Divide
Arithmetic (immediate)
divu Divide unsigned
addi Add immediate mfhi Move from HI
addiu Add immediate unsigned mthi Move to HI
slti Set on l. t. immediate mflo Move from LO
sltiu Set on less than unsigned mtlo Move to LO
andi AND immediate
ori OR immediate
xori Exclusive OR immediate
lui Load upper immediate 17 / 67
Computational Instructions
operation RD , RS , RT
18 / 67
Arithmetic Instruction Example
a b c f g h i j
$s0 $s1 $s2 $s3 $s4 $s5 $s6 $s7
19 / 67
Bitwise Logical Operator Example
li $v0, 1 # print_int
move $a0, $t2 # print contents of $t2
syscall
20 / 67
Immediate Computational Instructions
Example:
operation RD , RS , I
21 / 67
32-Bit Constants and lui
It is easy to load a register with a constant from
−32768 to 32767, e.g.,
31 30 ··· 2 1 0
31 30 ··· 2 1 0
25 / 67
Shift Right Arithmetic
31 30 29 28 ··· 3 2 1 0
26 / 67
Set on Less Than
27 / 67
Load and Store Instructions
Load/Store Instructions
lb Load byte
lbu Load byte unsigned The MIPS is a load/store
lh Load halfword architecture: data must
lhu Load halfword unsigned be moved into registers
lw Load word for computation.
lwl Load word left
lwr Load word right Other architectures e.g.,
sb Store byte (x86) allow arithmetic
sh Store halfword directly on data in
sw Store word memory.
swl Store word left
swr Store word right
28 / 67
Memory on the MIPS
Memory is byte-addressed.
Each byte consists of eight bits:
7 6 5 4 3 2 1 0
Bytes have non-negative integer addresses. Byte
addresses on the 32-bit MIPS processor are 32 bits;
64-bit processors usually have 64-bit addresses.
0: 7 6 5 4 3 2 1 0
1: 7 6 5 4 3 2 1 0
2: 7 6 5 4 3 2 1 0
..
.
232 − 1: 7 6 5 4 3 2 1 0
4 Gb total
29 / 67
Base Addressing in MIPS
+ 34 (immediate offset)
lb $t0, 34($t1)
42: EF
$t0: FFFFFFEF
30 / 67
Byte Load and Store
42: F0 42: F0
31 / 67
The Endian Question
MIPS can also load and Big Endian
store 4-byte words and
2-byte halfwords. 31 0
The endian question: byte 0 byte 1 byte 2 byte 3
when you read a word, in
what order do the bytes
appear?
Little Endian: Intel, DEC,
Little Endian
et al.
Big Endian: Motorola, 31 0
IBM, Sun, et al. byte 3 byte 2 byte 1 byte 0
MIPS can do either
SPIM adopts its host’s
convention
32 / 67
Testing Endianness
.data # Directive: ‘‘this is data’’
myword:
.word 0 # Define a word of data (=0)
.text # Directive: ‘‘this is program’’
main:
la $t1, myword # pseudoinstruction: load address
li $t0, 0x11
sb $t0, 0($t1) # Store 0x11 at byte 0
li $t0, 0x22
sb $t0, 1($t1) # Store 0x22 at byte 1
li $t0, 0x33
sb $t0, 2($t1) # Store 0x33 at byte 2
li $t0, 0x44
sb $t0, 3($t1) # Store 0x44 at byte 3
lw $t2, 0($t1) # 0x11223344 or 0x44332211?
j $ra
33 / 67
Alignment
Word and
half-word loads
and stores must
be aligned: lw $t0, 4($0) # OK
words must start lw $t0, 5($0) # BAD: 5 mod 4 = 1
at a multiple of lw $t0, 8($0) # OK
lw $t0, 12($0) # OK
4 bytes;
halfwords on a lh $t0, 2($0) # OK
multiple of 2. lh $t0, 3($0) # BAD: 3 mod 2 = 1
lh $t0, 4($0) # OK
Byte load/store
has no such
constraint.
34 / 67
Jump and Branch Instructions
35 / 67
Jumps
The simplest form,
j mylabel
# ...
mylabel:
# ...
sends control to the instruction at mylabel. Instruction
holds a 26-bit constant multiplied by four; top four bits
come from current PC. Uncommon.
Jump to register sends control to a 32-bit absolute
address in a register:
jr $t3
Instructions must be four-byte aligned;
the contents of the register must be a multiple of 4.
36 / 67
Jump and Link
mysub:
# ...
jr $ra # Jump back to caller
jalr is similar; target address supplied in a register.
37 / 67
Branches
38 / 67
Branches
Another family of branches tests a single register:
bgez $t0, myelse # Branch if $t0 positive
# ...
myelse:
# ...
Exception Instructions
tge tlt ... Conditional traps
break Breakpoint trap, for debugging
eret Return from exception
Multiprocessor Instructions
ll sc Load linked/store conditional for atomic operations
sync Read/Write fence: wait for all memory loads/stores
Coprocessor 0 Instructions (System Mgmt)
lwr lwl ... Cache control
tlbr tblwi ... TLB control (virtual memory)
... Many others (data movement, branches)
Floating-point Coprocessor Instructions
add.d sub.d ... Arithmetic and other functions
lwc1 swc1 ... Load/store to (32) floating-point registers
bct1t ... Conditional branches
41 / 67
Instruction Encoding
Jump-type: j, jal . . .
op:6 addr:26
42 / 67
Register-type Encoding Example
43 / 67
Register-type Shift Instructions
44 / 67
Immediate-type Encoding Example
45 / 67
Jump-Type Encoding Example
op:6 addr:26
jal 0x5014
46 / 67
Assembler Pseudoinstructions
Branch always b label → beq $0, $0, label
Branch if equal beqz s, label → beq s, $0, label
zero
slt $1, s, t
Branch greater or bge s, t, label →
beq $1, $0, label
equal
sltu $1, s, t
Branch greater or bgeu s, t, label →
beq $1, $0, label
equal unsigned
slt $1, t, s
Branch greater bgt s, t, label →
bne $1, $0, label
than
sltu $1, t, s
Branch greater bgtu s, t, label →
bne $1, $0, label
than unsigned
slt $1, s, t
Branch less than blt s, t, label →
bne $1, $0, label
sltu $1, s, t
Branch less than bltu s, t, label →
bne $1, $0, label
unsigned
47 / 67
Assembler Pseudoinstructions
Load immediate li d, j → ori d, $0, j
0 ≤ j ≤ 65535
Load immediate li d, j → addiu d, $0, j
−32768 ≤ j < 0
liu d, hi16(j)
Load immediate li d, j →
ori d, d, lo16(j)
Move move d, s → or d, s, $0
mult s, t
Multiply mul d, s, t →
mflo d
Negate unsigned negu d, s → subu d, $0, s
xor d, s, t
Set if equal seq d, s, t →
sltiu d, d, 1
slt d, s, t
Set if greater or sge d, s, t →
xori d, d, 1
equal
sltu d, s, t
Set if greater or sgeu d, s, t →
xori d, d, 1
equal unsigned
Set if greater than sgt d, s, t → slt d, t, s 48 / 67
Expressions
Initial expression:
x + y + z * (w + 3)
Reordered to minimize intermediate results; fully
parenthesized to make order of operation clear.
(((w + 3) * z) + y) + x
addiu $t0, $a0, 3 # w: $a0
mul $t0, $t0, $a3 # x: $a1
addu $t0, $t0, $a2 # y: $a2
addu $t0, $t0, $a1 # z: $a3
Consider an alternative:
(x + y) + ((w + 3) * z)
addu $t0, $a1, $a2
addiu $t1, $a0, 3 # Need a second temporary
mul $t1, $t1, $a3
addu $t0, $t0, $t1
49 / 67
Conditionals
50 / 67
Do-While Loops
a = 0; move $a0, $0 # a = 0
b = 0; move $a1, $0 # b = 0
do { li $t0, 10 # load constant
a = a + b; TOP:
b = b + 1; addu $a0, $a0, $a1 # a = a + b
} while (b != 10); addiu $a1, $a1, 1
# b = b + 1
bne $a1, $t0, TOP # b != 10?
51 / 67
While Loops
a = 0; move $a0, $0 # a = 0
b = 0; move $a1, $0 # b = 0
while (b != 10) { li $t0, 10
a = a + b; b TEST # test first
b = b + 1; BODY:
} addu $a0, $a0, $a1 # a = a + b
addiu $a1, $a1, 1 # b = b + 1
TEST:
bne $a1, $t0, BODY # b != 10?
52 / 67
For Loops
“Syntactic sugar” for a while loop
for (a = b = 0 ; b != 10 ; b++)
a += b;
is equivalent to move $a1, $0 # b = 0
move $a0, $a1 # a = b
a = b = 0; li $t0, 10
while (b != 10) { b TEST # test first
a = a + b; BODY:
b = b + 1; addu $a0, $a0, $a1 # a = a + b
} addiu $a1, $a1, 1 # b = b + 1
TEST:
bne $a1, $t0, BODY # b != 10?
53 / 67
Arrays
int a[5]; .comm a, 20 # Allocate 20
.text # Program next
void main() { main:
la $t0, a # Address of a
a[4] = a[3] = a[2] =
a[1] = a[0] = 3; li $t1, 3
sw $t1, 0($t0) # a[0]
a[1] = a[2] * 4; sw $t1, 4($t0) # a[1]
a[3] = a[4] * 2; sw $t1, 8($t0) # a[2]
} sw $t1, 12($t0) # a[3]
sw $t1, 16($t0) # a[4]
.
.
. lw $t1, 8($t0) # a[2]
0x10010010: a[4] sll $t1, $t1, 2 # * 4
0x1001000C: a[3] sw $t1, 4($t0) # a[1]
0x10010008: a[2] lw $t1, 16($t0) # a[4]
0x10010004: a[1] sll $t1, $t1, 1 # * 2
sw $t1, 12($t0) # a[3]
0x10010000: a[0]
. jr $ra
.
.
54 / 67
Summing the contents of an array
int i, s, a[10];
for (s = i = 0 ; i < 10 ; i++)
s = s + a[i];
move $a1, $0 # i = 0
move $a0, $a1 # s = 0
li $t0, 10
la $t1, a # base address of array
b TEST
BODY:
sll $t3, $a1, 2 # i * 4
addu $t3, $t1, $t3 # &a[i]
lw $t3, 0($t3) # fetch a[i]
addu $a0, $a0, $t3 # s += a[i]
addiu $a1, $a1, 1
TEST:
sltu $t2, $a1, $t0 # i < 10?
bne $t2, $0, BODY 55 / 67
Summing the contents of an array
int s, *i, a[10];
for (s=0, i = a+9 ; i >= a ; i--)
s += *i;
move $a0, $0 # s = 0
la $t0, a # &a[0]
addiu $t1, $t0, 36 # i = a + 9
b TEST
BODY:
lw $t2, 0($t1) # *i
addu $a0, $a0, $t2 # s += *i
addiu $t1, $t1, -4 # i--
TEST:
sltu $t2, $t1, $t0 # i < a
beq $t2, $0, BODY
56 / 67
Strings: Hello World in SPIM
# For SPIM: "Enable Mapped I/O" must be set
# under Simulator/Settings/MIPS
.data
hello:
.asciiz "Hello World!\n"
.text
main:
la $t1, 0xffff0000 # I/O base address
la $t0, hello
wait:
lw $t2, 8($t1) # Read Transmitter control
andi $t2, $t2, 0x1 # Test ready bit
beq $t2, $0, wait
lbu $t2, 0($t0) # Read the byte
beq $t2, $0, done # Check for terminating 0
sw $t2, 12($t1) # Write transmit data
addiu $t0, $t0, 1 # Advance to next character
b wait
done:
jr $ra 57 / 67
Hello World in SPIM: Memory contents
58 / 67
ASCII
0 1 2 3 4 5 6 7
0: NUL ’\0’ DLE 0 @ P ‘ p
1: SOH DC1 ! 1 A Q a q
2: STX DC2 " 2 B R b r
3: ETX DC3 # 3 C S c s
4: EOT DC4 $ 4 D T d t
5: ENQ NAK % 5 E U e u
6: ACK SYN & 6 F V f v
7: BEL ’\a’ ETB ’ 7 G W g w
8: BS ’\b’ CAN ( 8 H X h x
9: HT ’\t’ EM ) 9 I Y i y
A: LF ’\n’ SUB * : J Z j z
B: VT ’\v’ ESC + ; K [ k {
C: FF ’\f’ FS , < L \ l |
D: CR ’\r’ GS - = M ] m }
E: SO RS . > N ^ n ~
F: SI US / ? O _ o DEL
59 / 67
Subroutines
É Code reuse
Recurring computations aside from loops
Function libraries
É Isolation/Abstraction
Think Vegas:
What happens in a function stays in the function.
É Enabling Recursion
Fundamental to divide-and-conquer algorithms
60 / 67
Calling Conventions
# Call mysub: args in $a0,...,$a3
jal mysub
# Control returns here
# Return value in $v0 & $v1
# $s0,...,$s7, $gp, $sp, $fp, $ra unchanged
# $a0,...,$a3, $t0,...,$t9 possibly clobbered
61 / 67
The Stack
..
.
0x7FFFFFFC 0x32640128
0x7FFFFFF8 0xCAFE0B0E
Grows down
0x7FFFFFF4 0xDEADBEEF
0x7FFFFFF0 0xCODEFACE $sp
0x7FFFFFEC
..
.
62 / 67
Towers of Hanoi
63 / 67
hmove: $a0 $a1 $a2 $a3
addiu $sp, $sp, -24 src tmp dst n
beq $a3, $0, L1
Allocate 24 stack bytes:
sw $ra, 0($sp)
sw $s0, 4($sp) multiple of 8 for alignment
sw $s1, 8($sp) Check whether n == 0
sw $s2, 12($sp)
sw $s3, 16($sp) Save $ra, $s0, . . . , $s3 on
the stack
..
.
16($sp) $s3
12($sp) $s2
8($sp) $s1
4($sp) $s0
0($sp) $ra $sp
..
.
64 / 67
hmove:
addiu $sp, $sp, -24
beq $a3, $0, L1
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
sw $s2, 12($sp)
sw $s3, 16($sp)
move $s0, $a0 Save src in $s0
move $s1, $a1
move $s2, $a2 Save tmp in $s1
addiu $s3, $a3, -1 Save dst in $s2
Save n − 1 in $s3
64 / 67
hmove:
addiu $sp, $sp, -24
beq $a3, $0, L1
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
sw $s2, 12($sp)
sw $s3, 16($sp)
move $s0, $a0
move $s1, $a1
move $s2, $a2
addiu $s3, $a3, -1
move $a1, $s2 Call
move $a2, $s1
move $a3, $s3 hmove(src, dst, tmp, n−1)
jal hmove
64 / 67
hmove: li $v0, 1 # print_int
addiu $sp, $sp, -24 move $a0, $s2
beq $a3, $0, L1 syscall
sw $ra, 0($sp) li $v0,4 # print_str
sw $s0, 4($sp) la $a0, newline
sw $s1, 8($sp) syscall
sw $s2, 12($sp)
sw $s3, 16($sp) Print src -> dst
move $s0, $a0
move $s1, $a1
move $s2, $a2
addiu $s3, $a3, -1
move $a1, $s2
move $a2, $s1
move $a3, $s3
jal hmove
li $v0, 1 # print_int
move $a0, $s0
syscall
li $v0, 4 # print_str
la $a0, arrow
syscall 64 / 67
hmove: li $v0, 1 # print_int
addiu $sp, $sp, -24 move $a0, $s2
beq $a3, $0, L1 syscall
sw $ra, 0($sp) li $v0,4 # print_str
sw $s0, 4($sp) la $a0, newline
sw $s1, 8($sp) syscall
sw $s2, 12($sp) move $a0, $s1
sw $s3, 16($sp) move $a1, $s0
move $s0, $a0 move $a2, $s2
move $s1, $a1 move $a3, $s3
move $s2, $a2 jal hmove
addiu $s3, $a3, -1
Call
move $a1, $s2
move $a2, $s1 hmove(tmp, src, dst, n−1)
move $a3, $s3
jal hmove
li $v0, 1 # print_int
move $a0, $s0
syscall
li $v0, 4 # print_str
la $a0, arrow
syscall 64 / 67
hmove: li $v0, 1 # print_int
addiu $sp, $sp, -24 move $a0, $s2
beq $a3, $0, L1 syscall
sw $ra, 0($sp) li $v0,4 # print_str
sw $s0, 4($sp) la $a0, newline
sw $s1, 8($sp) syscall
sw $s2, 12($sp) move $a0, $s1
sw $s3, 16($sp) move $a1, $s0
move $s0, $a0 move $a2, $s2
move $s1, $a1 move $a3, $s3
move $s2, $a2 jal hmove
addiu $s3, $a3, -1 lw $ra, 0($sp)
move $a1, $s2 lw $s0, 4($sp)
move $a2, $s1 lw $s1, 8($sp)
move $a3, $s3 lw $s2, 12($sp)
jal hmove lw $s3, 16($sp)
li $v0, 1 # print_int
Restore variables
move $a0, $s0
syscall
li $v0, 4 # print_str
la $a0, arrow
syscall 64 / 67
hmove: li $v0, 1 # print_int
addiu $sp, $sp, -24 move $a0, $s2
beq $a3, $0, L1 syscall
sw $ra, 0($sp) li $v0,4 # print_str
sw $s0, 4($sp) la $a0, newline
sw $s1, 8($sp) syscall
sw $s2, 12($sp) move $a0, $s1
sw $s3, 16($sp) move $a1, $s0
move $s0, $a0 move $a2, $s2
move $s1, $a1 move $a3, $s3
move $s2, $a2 jal hmove
addiu $s3, $a3, -1 lw $ra, 0($sp)
move $a1, $s2 lw $s0, 4($sp)
move $a2, $s1 lw $s1, 8($sp)
move $a3, $s3 lw $s2, 12($sp)
jal hmove lw $s3, 16($sp)
li $v0, 1 # print_int L1:
move $a0, $s0 addiu $sp, $sp, 24 # free
syscall jr $ra # return
li $v0, 4 # print_str .data
la $a0, arrow arrow: .asciiz "->"
syscall newline: .asciiz "\n" 64 / 67
Factorial Example
int fact(int n) {
if (n < 1) return 1;
else return (n * fact(n - 1));
}
fact:
addiu $sp, $sp, -8 # allocate 2 words on stack
sw $ra, 4($sp) # save return address
sw $a0, 0($sp) # and n
slti $t0, $a0, 1 # n < 1?
beq $t0, $0, ELSE
li $v0, 1 # Yes, return 1
addiu $sp, $sp, 8 # Pop 2 words from stack
jr $ra # return
ELSE:
addiu $a0, $a0, -1 # No: compute n-1
jal fact # recurse (result in $v0)
lw $a0, 0($sp) # Restore n and
lw $ra, 4($sp) # return address
mul $v0, $a0, $v0 # Compute n * fact(n-1)
addiu $sp, $sp, 8 # Pop 2 words from stack
jr $ra # return
65 / 67
Memory Layout
Reserved
0x0000 0000
66 / 67
Differences in Other ISAs
More or fewer general-purpose registers (E.g., Itanium:
128; 6502: 3)
Arithmetic instructions affect condition codes (e.g.,
zero, carry); conditional branches test these flags
Registers that are more specialized (E.g., x86)
More addressing modes (E.g., x86: 6; VAX: 20)
Arithmetic instructions that also access memory (E.g.,
x86; VAX)
Arithmetic instructions on other data types (E.g., bytes
and halfwords)
Variable-length instructions (E.g., x86; ARM)
Predicated instructions (E.g., ARM, VLIW)
Single instructions that do much more (E.g., x86 string
move, procedure entry/exit)
67 / 67