Low Level C Programming
Low Level C Programming
CSEE W4840
Prof. Stephen A. Edwards
Columbia University
Spring 2011
Low-Level C Programming p.
Goals
Function is correct
Source code is concise, readable, maintainable
Time-critical sections of program run fast enough
Object code is small and efficient
Low-Level C Programming p.
Like Writing English
Low-Level C Programming p.
Arithmetic
Low-Level C Programming p.
Simple benchmarks
Low-Level C Programming p.
Simple benchmarks
Low-Level C Programming p.
C Arithmetic Trivia
Low-Level C Programming p.
Arithmetic Lessons
Low-Level C Programming p.
Bit Manipulation
Low-Level C Programming p.
Bit-manipulation basics
e >>= 2; /* Divide e by 4 */
Low-Level C Programming p. 1
Advanced bit manipulation
Low-Level C Programming p. 1
Faking Multiplication
101011
1101
101011
= 43 + 43 << 2 + 43 << 3 = 559
10101100
+101011000
1000101111
Low-Level C Programming p. 1
Faking Multiplication
101011
1110
= 43 << 1 + 43 << 2 + 43 << 3
1010110
= 43 << 4 - 43 << 2
10101100
= 602
+101011000
1001011010
Only useful
switch (a) {
if (a == 1) case 1:
foo(); foo(); break;
else if (a == 2) case 2:
bar(); bar(); break;
else if (a == 3) case 3:
baz(); baz(); break;
else if (a == 4) case 4:
qux(); qux(); break;
else if (a == 5) case 5:
quux(); quux(); break;
else if (a == 6) case 6:
corge(); corge(); break;
}
Low-Level C Programming p. 1
Nios code for if-then-else
Low-Level C Programming p. 1
Nios code for switch (1)
ldw r2, 0(fp) # Fetch a
cmpgeui r2, r2, 7 # Compare with 7
bne r2, zero, .L2 # Branch if greater or equal
ldw r2, 0(fp) # Fetch a
muli r3, r2, 4 # Multiply by 4
movhi r2, %hiadj(.L9) # Load address .L9
addi r2, r2, %lo(.L9)
add r2, r3, r2 # = a * 4 + .L9
ldw r2, 0(r2) # Fetch from jump table
jmp r2 # Jump to label
.section .rodata
.align 2
.L9:
.long .L2 # Branch table
.long .L3
.long .L4
.long .L5
.long .L6
.long .L7
.long .L8
Low-Level C Programming p. 1
Nios code for switch (2)
.section .text
.L3:
call foo
br .L2
.L4:
call bar
br .L2
.L5:
call baz
br .L2
.L6:
call qux
br .L2
.L7:
call quux
br .L2
.L8:
call corge
.L2:
Low-Level C Programming p. 1
Computing Discrete Functions
Low-Level C Programming p. 1
Computing Discrete Functions
Low-Level C Programming p. 2
Function calls
Low-Level C Programming p. 2
Code for foo() (unoptimized)
foo:
addi sp, sp, -20 # Allocate space on stack
stw ra, 16(sp) # Store return address
stw fp, 12(sp) # Store frame pointer
mov fp, sp # Frame pointer is new SP
stw r4, 0(fp) # Save a on stack
stw r5, 4(fp) # Save b on stack
Low-Level C Programming p. 2
Code for foo() (optimized)
foo:
addi sp, sp, -4 # Allocate stack space
stw ra, 0(sp) # Store return address
mov r2, r4 # Swap arguments (r4, r5)
mov r4, r5 # using r2 as temporary
mov r5, r2
call bar # Call bar() (return in r2)
ldw ra, 0(sp) # Restore return address
addi sp, sp, 4 # Release stack space
ret # Return from subroutine
Low-Level C Programming p. 2
Strength Reduction
Low-Level C Programming p. 2
Unoptimized array code (fragment)
.L2:
ldw r2, 0(fp) # Fetch i
cmpgei r2, r2, 10 # i >= 10?
bne r2, zero, .L1 # exit if true
movhi r3, %hiadj(foo) # Get address of foo array
addi r3, r3, %lo(foo)
ldw r2, 0(fp) # Fetch i
muli r2, r2, 12 # i * 12
add r3, r2, r3 # foo[i]
movi r2, 77
stw r2, 0(r3) # foo[i].a = 77
movhi r3, %hiadj(foo)
addi r3, r3, %lo(foo)
ldw r2, 0(fp)
muli r2, r2, 12
add r2, r2, r3 # compute &foo[i]
addi r3, r2, 4 # offset for b field
movi r2, 88
stb r2, 0(r3) # foo[i].b = 88
Low-Level C Programming p. 2
Unoptimized pointer code (fragment)
.L2:
ldw r3, 0(fp) # fp
ldw r2, 4(fp) # fe
beq r3, r2, .L1 # fp == fe?
ldw r3, 0(fp)
movi r2, 77
stw r2, 0(r3) # fp->a = 77
ldw r3, 0(fp)
movi r2, 88
stb r2, 4(r3) # fp->b = 88
ldw r3, 0(fp)
movi r2, 99
stw r2, 8(r3) # fp->c = 99
ldw r2, 0(fp)
addi r2, r2, 12
stw r2, 0(fp) # ++fp
br .L2
Low-Level C Programming p. 2
Optimized (O2) array code
Low-Level C Programming p. 2
Optimized (O2) pointer code
Low-Level C Programming p. 2
How Rapid is Rapid?
Low-Level C Programming p. 2
Double-checking
.L5: # cycles
ldw r2, 0(r4) # Fetch b[i] 2-7
addi r3, r3, -1 # --i 1
addi r4, r4, 4 # next b element 1
add r5, r5, r2 # a += b[i] 1
bne r3, zero, .L5 # repeat if i > 0 3
mov r2, r5 # result
ret
Low-Level C Programming p. 3
Features in order of increasing cost
1. Integer arithmetic
2. Pointer access
3. Simple conditionals and loops
4. Static and automatic variable access
5. Array access
6. Floating-point with hardware support
7. Switch statements
8. Function calls
9. Floating-point emulation in software
10. Malloc() and free()
11. Library functions (sin, log, printf, etc.)
12. Operating system calls (open, sbrk, etc.)
Low-Level C Programming p. 3
Storage Classes in C
0
free()
0
malloc( )
Low-Level C Programming p. 3
Dynamic Storage Allocation
Rules:
Each allocated block contiguous (no holes)
Blocks stay fixed once allocated
malloc()
Find an area large enough for requested block
Mark memory as allocated
free()
Mark the block as unallocated
Low-Level C Programming p. 3
Simple Dynamic Storage Allocation
Simplest: First-fit
Low-Level C Programming p. 3
Dynamic Storage Allocation
S N S S N
malloc( )
S S N S S N
Low-Level C Programming p. 3
Simple Dynamic Storage Allocation
S S N S S N
free()
S S N
Low-Level C Programming p. 3
Storage Classes Compared
#define SWITCHES \
((volatile char *) 0x1800)
#define LEDS \
((volatile char *) 0x1810)
void main() {
for (;;) {
*LEDS = *SWITCHES;
}
}
Low-Level C Programming p. 4
Whats With the Volatile?
int main() {
alt_u8 sw;
for (;;) {
sw = IORD_ALTERA_AVALON_PIO_DATA(SWITCHES_BASE);
IOWR_ALTERA_AVALON_PIO_DATA(LEDS_BASE, sw);
}
}
Handbook)
HW/SW Communication Styles
Low-Level C Programming p. 4
Unix Signals
void handleint() {
printf("Got an INT\n");
/* some variants require this */
signal(SIGINT, handleint);
}
int main() {
/* Register signal handler */
signal(SIGINT, handleint);
/* Do nothing forever */
for (;;) { }
return 0; Low-Level C Programming p. 4
}
Interrupts under Altera (1)
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
Low-Level C Programming p. 4
Interrupts under Altera (2)
#include "sys/alt_irq.h"
#include "system.h"
'
ft
r
s-
V\
;
-
I
? i
V
0
!
*O
f* f
11 i
(y) ?
-a- ft
A
-- ;
-*.
Low-Level C Programming p. 4
The Edwards Way to Debug
Low-Level C Programming p. 4