VBCC
VBCC
Volker Barthelmann
February 2022
i
Table of Contents
1 General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Legal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3.1 Installing for Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.2 Installing for DOS/Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.3 Installing for AmigaOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.4 Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2 The Frontend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1 Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3 The Compiler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.1 General Compiler Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2 Errors and Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.4 Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4.1 Register Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4.2 Flow Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4.3 Common Subexpression Elimination . . . . . . . . . . . . . . . . . . . . . . 20
3.4.4 Copy Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.5 Constant Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.6 Dead Code Elimination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.4.7 Loop-Invariant Code Motion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.4.8 Strength Reduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.4.9 Induction Variable Elimination. . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.4.10 Loop Unrolling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.4.11 Function Inlining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.4.12 Intrinsic Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.4.13 Unused Object Elimination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.4.14 Alias Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.4.15 Inter-Procedural Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.4.16 Cross-Module Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.4.17 Instruction Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.4.18 Target-Specific Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.4.19 Debugging Optimized Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.5 Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.5.1 Pragmas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.5.2 Register Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.5.3 Inline-Assembly Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.5.4 Variable Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
ii vbcc manual
4 M68k/Coldfire Backend . . . . . . . . . . . . . . . . . . . . . . . 41
4.1 Additional options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.2 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.3 Small data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.4 Small code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.5 CPUs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.6 FPUs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.7 Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.8 Target-Specific Variable Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.9 Target-specific pragmas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.10 Predefined Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.11 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.12 Stdarg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.13 Known problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5 PowerPC Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.1 Additional options for this version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.2 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.3 Target-specific variable-attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.4 Target-specific pragmas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.5 Predefined Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.6 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.7 Stdarg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.8 Known problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7 i386 Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.1 Additional options for this version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.2 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.3 Predefined Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.4 Stdarg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.5 Known Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
8 c16x Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
8.1 Additional options for this version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
8.2 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
8.3 Target-specific variable-attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
8.4 Target-specific type-attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.5 Target-specific types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.6 Predefined Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.7 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
8.8 Stdarg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
8.9 Known Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
9 68hc12 Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
9.1 Additional options for this version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
9.2 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
9.3 Target-specific variable-attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
9.4 Predefined Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
9.5 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
9.6 Stdarg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
9.7 Known Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
10 VideoCore IV Backend . . . . . . . . . . . . . . . . . . . . . . . 69
10.1 Additional options for this version . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.2 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.3 Target-specific variable-attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.4 Target-specific pragmas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.5 Predefined Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.6 Stdarg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.7 Known problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
11 6502 Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
11.1 Additional options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
11.2 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
11.3 Math. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
11.3.1 Floating Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
11.4 Target-Specific Variable Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
11.5 Target-Specific #pragmas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
11.6 Predefined Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
11.7 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
11.8 Banking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
iv vbcc manual
12 Instruction Scheduler . . . . . . . . . . . . . . . . . . . . . . . . . 81
12.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
12.2 Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
12.3 Known problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
13 Code Compressor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.2 Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.3 Known problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.4 Backend Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.4.1 Building vcpr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.4.2 Basic Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.4.3 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
13.4.4 Backend Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
13.4.5 Backend Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
13.4.6 Frontend Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
14 C Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.2 Legal. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.3 Global Variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
14.3.1 timezone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
14.4 Embedded Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
14.4.1 Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
14.4.2 Heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
14.4.3 Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
14.4.4 CTRL-C Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
14.4.5 Floating Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
14.4.6 Useless Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
14.4.7 Linking/Locating . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
14.5 AmigaOS/68k . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
14.5.1 Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
14.5.2 Floating point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
14.5.3 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14.5.4 Small data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
v
14.5.5 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
14.5.6 Minimal Startup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
14.5.7 Minimal Startup for resident programs . . . . . . . . . . . . . . . . . . . 94
14.5.8 amiga.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
14.5.9 auto.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
14.5.10 reaction.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
14.6 Kickstart1.x/68k . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
14.6.1 Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
14.6.2 Floating point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
14.6.3 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.6.4 Small data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.6.5 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.6.6 amiga.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.6.7 auto.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.6.8 Minimal Startup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.6.9 Minimal Startup for Resident Programs . . . . . . . . . . . . . . . . . . 97
14.7 PowerUp/PPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.7.1 Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.7.2 Floating point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.7.3 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.7.4 Small data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.7.5 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.7.6 Minimal Startup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.7.7 libamiga.a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.7.8 libauto.a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.8 WarpOS/PPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.8.1 Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.8.2 Floating point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.8.3 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.8.4 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.8.5 amiga.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.8.6 auto.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.9 MorphOS/PPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.9.1 Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.9.2 Floating point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.9.3 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.9.4 Small data model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.9.5 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.9.6 libamiga.a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
14.9.7 libauto.a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
14.10 AmigaOS4/PPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
14.10.1 Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
14.10.2 Floating point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
14.10.3 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
14.10.4 Small data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
14.10.5 Dynamic linking. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
14.10.6 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
14.10.7 libamiga.a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
vi vbcc manual
1 General
1.1 Introduction
vbcc is a highly optimizing portable and retargetable ISO C compiler. It supports ISO
C according to ISO/IEC 9899:1989 and a subset of the new standard ISO/IEC 9899:1999
(C99).
It is split into a target-independent and a target-dependent part, and provides complete
abstraction of host- and target-arithmetic. Therefore, it fully supports cross-compiling for
8, 16, 32 and 64bit architectures.
Embedded systems are supported by features like different pointer-sizes (e.g. differently
sized function- and object-pointers or near- and far-pointers), ROM-able code, inline-
assembly, bit-types, interrupt-handlers, section-attributes, stack-calculation and many oth-
ers (depending on the backend).
vbcc provides a large set of aggressive high-level optimizations (see Section 3.4 [Optimiza-
tions], page 17) as well as target-specific optimizations to produce faster or smaller code.
Rather than restricting analysis and optimization to single functions or files, vbcc is able
to optimize across functions and even modules. Target-independent optimizations include:
− cross-module function-inlining
− partial inlining of recursive functions
− inter-procedural data-flow analysis
− inter-procedural register-allocation
− register-allocation for global variables
− global common-subexpression-elimination
− global constant-propagation
− global copy-propagation
− dead-code-elimination
− alias-analysis
− loop-unrolling
− induction-variable elimination
− loop-invariant code-motion
− loop-reversal
1.2 Legal
vbcc is copyright in 1995-2022 by Volker Barthelmann.
This archive may be redistributed without modifications and used for non-commercial pur-
poses.
An exception for commercial usage is granted, provided that the target CPU is M68k and
the target OS is AmigaOS. Resulting binaries may be distributed commercially without
further licensing.
2 vbcc manual
An exception for commercial usage is granted, provided that the target CPU is 6502 with
MEGA65 extensions and the target HW is MEGA65. Resulting binaries may be distributed
commercially without further licensing.
In all other cases you need my written consent.
This copyright applies to vc, vbcc, vsc and vcpr.
This archive may contain other tools (e.g. assemblers or linkers) which do not fall under
this license. Please consult the corresponding documentation of these tools.
vbcc contains the preprocessor ucpp by Thomas Pornin. Included is the copyright notice of
ucpp (note that this license does not apply to vbcc or any other part of this distribution):
/*
* (c) Thomas Pornin 1999, 2000
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. The name of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED ‘‘AS IS’’ AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
1.3 Installation
The vbcc directory tree looks as follows:
vbcc/targets/<target>
Subdirectory containing all files specific to a certain target (e.g. m68k-amigaos
or ppc-eabi).
or
setenv VBCC <prefix>/vbcc
or
setenv PATH <prefix>/vbcc/bin:"$PATH"
vbcc_bin_warpos
Additional PPC-native binaries using the WarpOS kernel for AmigaOS 3.x.
vbcc_target_m68k-kick13
Header files and libraries for AmigaOS 1.x/M68k.
vbcc_target_m68k-amigaos
Header files and libraries for AmigaOS 2.x/3.x/M68k.
vbcc_target_ppc-amigaos
Header files and libraries for AmigaOS 4.x.
vbcc_target_ppc-morphos
Header files and libraries for MorphOS.
vbcc_target_ppc-powerup
Header files and libraries for PowerUp.
vbcc_target_ppc-warpos
Header files and libraries for WarpOS.
Usually you will install the binary archive for your host architecture of choice, then add as
many target archives you need.
When installing manually it is recommended to add the following assigns to your
s:User-Startup file (only do the assignments required for the installed targets):
assign >NIL: vbcc: <path to vbcc directory>
assign >NIL: C: vbcc:bin add
Also, the stack-size has to be increased from the default, for those binaries which don’t
do that automatically (e.g. AmigaOS4). 64KB is a sensible value, for very large projects
higher values might be necessary.
For writing AmigaOS/MorphOS programs you will need the appropriate system header
files. Please use NDK 3.9 or later for AmigaOS 2.x/3.x, as the proto/inline headers have
been created with it.
For AmigaOS 1.x you should use the old Kickstart 1.x headers from that time. It makes
sure that you don’t use a feature of later OS releases.
There are different configuration files provided in the config-subdirectory to choose differ-
ent targets (i.e. the system you want to generate programs for) and hosts (i.e. the system
you want the compiler an tools to run on). The general naming-scheme for these files is
<target> <host>.
Available config files, when all targets are installed, are
aos68k AmigaOS 2.x/3.x.
aos68km AmigaOS 2.x/3.x with minimal startup code.
aos68kr AmigaOS 2.x/3.x for resident programs.
kick13 AmigaOS 1.x.
kick13m AmigaOS 1.x with minimal startup code.
kick13r AmigaOS 1.x for resident programs.
aosppc AmigaOS 4.x on PPC using vclib.
newlib AmigaOS 4.x on PPC using newlib.
morphos PPC systems running MorphOS.
powerup PPC boards using the PowerUp system.
warpos PPC boards using the WarpOS system.
You can choose one of these systems using the +-option of vc, e.g.
vc +aos68k_powerup ...
will compile for AmigaOS/68k using the compiler running on PowerUp.
You may choose to create copies of some of these configuration files with simpler names.
E.g. if you usually want the compiler to run on WarpOS you could copy aos68k_warpos
to aos68k, warpos_warpos to warpos and so on. Then you can just specify the target and
your preferred host system will be chosen automatically.
Additionally, you may copy the configuration file for your preferred host/target-combination
to vc.config. This configuration will be chosen by default if you do not specify anything.
By default, the target-only-specifications use 68020-native tools on AmigaOS 2.x/3.x - e.g.
+warpos will create code for WarpOS, but the compiler and tools will run on the 68k. The
6 vbcc manual
default vc.config will then create code for 68k using tools running on 68k. Having installed
the MorphOS-native binary archive instead, the default vc.config will create PPC code
for MorphOS using tools running on MorphOS.
1.4 Tutorial
Now you should be able to use vbcc. To compile and link the program hello.c, type
vc hello.c
The file hello.c will be compiled and linked, using the default configuration from
vc.config, to create the executable a.out in the current directory.
vc hello.c -o hello
will do the same, but the created executable will be called hello.
vc -c t1.c t2.c
will compile t1.c and t2.c without linking, creating the object files t1.o and t2.o.
vc t1.o t2.o -o tt
will link them together and create the executable tt.
If your program uses floating point, you may have to link with a math-library. The details
are dependent on the target, but usually -lm will be suitable (for AmigaOS on m68k choose
one of -lmieee, -lm881, -lm040 or -lm060).
vc calc.c -o calc -lm
7
2 The Frontend
This chapter describes vc, the frontend for vbcc. It knows how to deal with different file
types and optimization settings and will call the compiler, assembler and linker. It is not
recommended to call the different translation-phases directly. vc provides an easy-to-use
interface which is mostly compatible to Unix cc.
2.1 Usage
The general syntax for calling vc
vc [options] file1 file2 ...
processes all files according to their suffix and links all objects together (unless any of -E,
-S, -c is specified). The following file types are recognized:
.c C source
.i already preprocessed C source
.scs assembly source to be fed to the scheduler
.asm
.s assembly source
.obj
.o object file
Usually pattern matching is supported - however this depends on the port and the host
system.
The options recognized by vc are:
-v Verbose mode. Prints all commands before executing them.
-vv Very verbose. Displays some internals as well.
-Ox Sets the optimization level.
-O0 is equivalent to -O=0.
-O will activate some optimizations (at the moment -O=991).
-O2 will activate most optimizations (at the moment -O=1023 -schedule).
-O3 will activate all optimizations (at the moment -O=~0 -schedule).
-O4 will activate full cross-module-optimization.
can not be linked directly. Also, make sure to pass all relevant compiler options
also to the linker-command.
Higher values may or may not activate even more optimizations. The default
is -O=1. It is also possible to specify an exact value with -O=n. However, I do
not recommend this unless you know exactly what you are doing.
-SCS Do not schedule. Save the compiled files with .scs suffix.
-k Keep all intermediate files. By default all generated files except the source files
and the targets are deleted.
-Ipath Add path to the include-search-path. An empty path adds the current direc-
tory.
-Lpath Add path to the library-search-path. This is passed through to the linker.
-static Instruct the linker to link against static libraries. This may override the default
to link against dynamic libraries first.
-nostdlib
Do not link with standard-startup/libraries. Useful only for people who know
what they are doing.
-notmpfile
Do not use names from tmpnam() for temporary files.
-schedule
Invoke the instruction-scheduler, if available.
-rmcfg-<opt>
Ignore all lines from the config file starting with -<opt>.
2.2 Configuration
vc needs a config file to know how to call all the translation phases (compiler, assembler,
linker). Unless a different file is specified using the +-option, it will look for a file vc.config
(vc.cfg for DOS/Windows).
On AmigaOS vc will search in the current directory, in ENV: and VBCC:.
On Unix vc will search in the current directory followed by /etc/.
On DOS/Windows it will search in the current directory.
If the config file was not found in the default search-paths and an environment variable
$VBCC is set, vc will also look in $VBCC/config.
Once a config file is found, it will be treated as a collection of additional command line
arguments. Every line of the file will be used as one argument. So no quoting shall be used
and furthermore must each argument be placed on its own line.
The following options can be used to tell vc how to call the translation phases (they will
usually be contained in the config-file):
-pp=string
The preprocessor will be called like in printf(string,opts,infile,outfile),
e.g. the default for vcpp searching the includes in vinclude: and defining __
STDC__) is -pp=vcpp -Ivinclude: -D__STDC__=1 %s %s %s. Note that there is
an internal preprocessor, called ucpp, since V0.8, you usually don’t need this
option any more.
-cc=string
For the compiler. Note that you cannot use vc to call another compiler than
vbcc. But you can call different versions of vbcc this way, e.g.: -cc=vbccm68k
-quiet or -cc=vbcci386 -quiet
-isc=string
The same for the scheduler, e.g.: -isc=vscppc -quiet %s %s Omit, if there is
no scheduler for the architecture.
-as=string
The same for the assembler, e.g.: -as=vasmm68k_mot -quiet -Fhunk -phxass
-opt-pea -opt-clr %s -o %s or -as=as %s -o %s
-rm=string
This is the string for the delete command and takes only one argument, e.g.
-rm=delete quiet %s or -rm=rm %s
-ld=string
This is for the linker and takes three arguments. The first one are the object files
(separated by spaces), the second one the user specified libraries and the last one
the name of the resulting executable. This has to link with proper startup-code
and c-libraries, e.g.: -ld=vlink -x -Bstatic -Cvbcc -nostdlib -Lvlibos3:
vlibos3:startup.o %s %s -lvc -o %s or -ld=ld /usr/lib/crt0.o %s %s -lc
-o %s
-l2=string
The same like -ld, but standard-startup and -libraries should not be linked;
used when -nostdlib is specified.
10 vbcc manual
-ldnodb=string
This option string is inserted in the linker command before specifying the li-
braries, whenever an executable without debugging information and symbols
should be created (AKA as a ’stripped’ executable).
-ldstatic=string
This option string is inserted in the linker command before specifying the li-
braries when static linking was requested with option -static.
All those strings should tell the command to omit any output apart from error messages
if possible. However for every of those options there exists one with an additional ‘v’, i.e.
-ppv=, -asv=, etc. which should produce some output, if possible. If vc is invoked with the
-vv option the verbose commands will be called, if not the quiet ones will be used.
‘-ul=string’
Format for additional libraries specified with -l<lib>. The result of
printf(string,lib) will be added to the command invoking the linker.
Examples are: -ul=vlib:%s.lib or -ul=-l%s
11
3 The Compiler
This chapter describes the target-independent part of the compiler. It documents the op-
tions and extensions which are not specific to a certain target. Be sure to also read the
chapter on the backend you are using. It will likely contain important additional information
like data-representation or additional options.
-cmd=<file>
A file containing additional command line options can be specified using this
command. This may be useful for very long command lines.
-c89
-c99 Set the C standard to be used. The default is the 1999 ISO C standard
(ISO/IEC9899:1999). Currently the following changes of C99 are handled:
− long long int (not supported by all backends)
− flexible array members as last element of a struct
− mixed statements and declarations
− declarations within for-loops
− inline function-specifier
− restrict-qualifier
− new reserved keywords
− //-comments
− vararg-macros
− _Pragma
− implicit int deprecated
− implicit function-declarations deprecated
− increased translation-limits
− designated initializers
− non-constant initializers for automatic aggregates
− compound literals
− variable-length arrays (incomplete)
-unsigned-char
Make the unqualified type of char unsigned.
-maxoptpasses=n
Set maximum number of optimizer passes to n. See Section 3.4 [Optimizations],
page 17.
-inline-size=n
Set the maximum ’size’ of functions to be inlined. See Section 3.4.11 [Function
Inlining], page 26.
-inline-depth=n
Inline functions up to n nesting-levels (including recursive calls). The default
value is 1. Be careful with values greater than 2. See Section 3.4.11 [Function
Inlining], page 26.
-unroll-size=n
Set the maximum ’size’ of unrolled loops. See Section 3.4.10 [Loop Unrolling],
page 24.
Chapter 3: The Compiler 13
-unroll-all
Unroll loops with a non-constant number of iterations if the number can be cal-
culated at runtime before entering the loop. See Section 3.4.10 [Loop Unrolling],
page 24.
-no-inline-peephole
Some backends provide peephole-optimizers which perform simple optimiza-
tions on the assembly code output by vbcc. By default, these optimizations
will also be performed on inline-assembly code of the application. This switch
turns off this behaviour. See Section 3.5.3 [Inline-Assembly Functions], page 34.
-fp-associative
Floating point operations do not obey the law of associativity, e.g.
(a+b)+c==a+(b+c) is not true for all floating point numbers a,b,c. Therefore
certain optimizations depending on this property cannot be performed on
floating point numbers.
This option tells vbcc to treat floating point operations as associative and
perform those optimizations even if that may change the results in some cases
(not ISO conforming).
-no-alias-opt
Do not perform type-based alias analysis. See Section 3.4.14 [Alias Analysis],
page 29.
-no-multiple-ccs
If the backend supports multiple condition code registers, vbcc will try to use
them when optimizing. This flag prevents vbcc from using them.
-double-push
On targets where function-arguments are passed in registers but also stack-slots
are left empty for such arguments, pass those arguments both in registers and
on the stack.
This generates less efficient code but some broken code (e.g. code which calls
varargs functions without correct prototypes in scope) may work.
-short-push
In the presence of a prototype, no promotion will be done on function argu-
ments. For example, <char> will be passed as <char> rather than <int> and
<float> will not be promoted to <double>. This may be more efficient on small
targets.
However, please note that this feature may not be supported by all backends
and that using this option breaks ANSI/ISO conformance. For example, a
function with a <char> parameter must never be called without a prototype in
scope.
-soft-float
On targets supporting this flag, software floating point emulation will be used
rather than a hardware FPU. Please consult the corresponding backend docu-
mentation when using this flag.
14 vbcc manual
-stack-check
Insert code for dynamic stack checking/extending if the backend and the envi-
ronment support this feature.
-ansi
-iso Switch to ANSI/ISO mode.
− In ISO mode warning 209 will be printed by default.
− Inline-assembly functions are not recognized.
− Assignments between pointers to <type> and pointers to unsigned <type>
will cause warnings.
-maxerrors=n
Abort the compilation after n errors; do not stop if n==0.
-dontwarn=n[,n...]
Suppress warning number n; suppress all warnings if n<0. Multiple warnings
may be separated by commas. See Section 3.2 [Errors and Warnings], page 16,
-warn=n Turn on warning number n; turn on all warnings if n<0. See Section 3.2 [Errors
and Warnings], page 16,
-no-cpp-warn
Turn off all preprocessor warnings.
-warnings-as-errors
Treat all enabled warnings as errors.
-strip-path
Strip the path of filenames from error messages. Error messages may look more
convenient that way, but message browsers or similar programs might need full
paths.
-no-include-stack
Do not display the include stack in error messages.
-+
-cpp-comments
Allow C++ style comments (not ISO89 conforming).
-no-trigraphs
Do not recognize trigraphs (not ISO conforming).
-E Write the preprocessor output to <file>.i.
-deps Write a make-style dependency-line to <file>.dep.
-deps-for-libs
By default, -deps will not include files that are included using the syntax
#include <...>. Specify this option to add those files as well.
-depobj=<file>
Use the specified filename as target in the generated dependency file instead of
basing it on the input file name.
Chapter 3: The Compiler 15
-reserve-reg=<register>
Reserve that register not to be used by the backend. This option is dangerous
and must only be used for registers otherwise available for the register allocator.
If it used for special registers or registers used internally by the backend, it may
be ignored, lead to corrupt code or even cause internal errors from the compiler.
Only use if you know what you are doing!
-dontkeep-initialized-data
By default vbcc keeps all data of initializations in memory during the whole
compilation (it can sometimes make use of this when optimizing). This can
take some amount of memory, though. This options tells vbcc to keep as little
of this data in memory as possible. This has not yet been tested very well.
-prefer-statics
Assign auto variables to static memory rather than the stack if it can be de-
duced that the function is not called recursively, i.e. the behaviour is still C
compliant. This may be more efficient on targets that can access static data
faster than stack. While stack-usage is reduced, total memory consumption is
usually increased.
Functions will not be re-entrant any more.
This option only has effect on higher optimization levels (-O3).
-force-statics
Like -prefer-statics, but assume all functions as non-recursive. This will
break C compliance.
This option only has effect on higher optimization levels (-O).
-range-opt
Perform additional optimizations based on value range analysis. This option is
under development and considered experimental. The following optimizations
are currently implemented:
− Induction variables of some loops are transformed to smaller types if it can
be determined that they will only get assigned values that fit into a smaller
type.
-merge-strings
Overlay identical string-constants to save memory. Currently only strings iden-
tical to string-constants on top-level are recognized.
-sec-per-obj
Tells the backend to put every function/object into its own separate section.
This allows more fine-grained elimination of unused functions/objects by the
linker. On the other hand, it may prevent some optimizations by the assembler.
This option only has effect if it is supported by the backend.
-mask-opt
Perform mask optimizations on suitable library function. This will create calls
to optimized versions of e.g. the printf/scanf family of functions.
The assembler output will be saved to file.asm (if file already contained a suffix, this
will first be removed; same applies to .ic1/.ic2)
16 vbcc manual
long double
The default signedness for integer types is signed.
Depending on the backend, some of these types can have identical representation. The
representation (size, alignment etc.) of these types usually varies between different backends.
vbcc is able to support arbitrary implementations.
Backends may be restricted and omit some types (e.g. floating point on small embedded
architectures) or offer additional types. E.g. some backends may provide special bit types
or different pointer types.
3.4 Optimizations
vbcc offers different levels of optimization, ranging from fast compilation with straight-
forward code suitable for easy debugging to highly aggressive cross-module optimizations
delivering very fast and/or tight code.
This section describes the general phases of compilation and gives a short overview on the
available optimizations.
In the first compilation phase every function is parsed into a tree structure one expression
after the other. Type-checking and some minor optimizations like constant-folding or some
algebraic simplifications are done on the trees. This phase of the translation is identical in
optimizing and non-optimizing compilation.
Then intermediate code is generated from the trees. In non-optimizing compilation tem-
poraries needed to evaluate the expression are immediately assigned to registers while in
optimizing compilation, a new variable is generated for each temporary. Slightly different
intermediate code is produced in optimizing compilation. Some minor optimizations are
performed while generating the intermediate code (simple elimination of unreachable code,
some optimizations on branches etc.).
After intermediate code for the whole function has been generated, simple register allocation
may be done in non-optimizing compilation if bit 1 has been set in the -O option. Afterwards,
the intermediate code is passed to the code generator and then all memory for the function,
its variables etc. is freed.
In optimizing compilation flowgraphs are constructed, data flow analysis is performed and
many passes are made over the function’s intermediate code. Code may be moved around,
new variables may be added, other variables removed etc. etc. (for more detailed informa-
tion on the optimizations look at the description for the -O option below).
Many of the optimization routines depend on each other. If one routine finds an optimiza-
tion, this often enables other routines to find further ones. Also, some routines only do a
first step and let other routines ’clean up’ afterwards. Therefore vbcc usually makes many
passes until no further optimizations are found. To avoid possible extremely long optimiza-
tion times, the number of those passes can be limited with -maxoptpasses (the default is
max. 10 passes). vbcc will display a warning if more passes might be useful.
Depending on the optimization level, a whole translation-unit or even several translation-
units will be read at once. Also, the intermediate code for all functions may be kept in
memory during the entire compilation. Be aware that higher optimization levels can take
much more time and memory to complete.
18 vbcc manual
The following table lists the optimizations which are activated by bits in the argument of
the -O option. Note that not all combinations are valid. It is heavily recommended not
to fiddle with this option but just use one of the settings provided by vc (e.g. -O0 - -O4).
These options also automatically handle actions like invoking the scheduler or cross-module
optimizer.
Bit 0 (1) Perform Register allocation. See Section 3.4.1 [Register Allocation], page 19.
Bit 1 (2) This flag turns on the optimizer. If it is set to zero, no global optimizations will
be performed, no matter what the other flags are set to. Slightly different inter-
mediate code will be generated by the first translation phases and a flowgraph
will be constructed. See Section 3.4.2 [Flow Optimizations], page 19.
Bit 2 (4) Perform common subexpression elimination (see Section 3.4.3 [Common Subex-
pression Elimination], page 20) and copy propagation (see Section 3.4.4 [Copy
Propagation], page 21). This can be done globally or only within basic blocks
depending on bit 5.
Bit 3 (8) Perform constant propagation (see Section 3.4.5 [Constant Propagation],
page 21). This can be done globally or only within basic blocks depending on
bit 5.
Bit 4 (16) Perform dead code elimination (see Section 3.4.6 [Dead Code Elimination],
page 22).
Bit 5 (32) Some optimizations are available in local and global versions. This flag turns
on the global versions. Several major optimizations will not be performed and
only one optimization pass is done unless this flag is set.
Bit 6 (64) Reserved.
Bit 7 (128)
vbcc will try to identify loops and perform some loop optimizations. See
Section 3.4.8 [Strength Reduction], page 23, and Section 3.4.7 [Loop-Invariant
Code Motion], page 22. These only work if bit 5 (32) is set.
Bit 8 (256)
vbcc tries to place variables at the same memory addresses if possible (see
Section 3.4.13 [Unused Object Elimination], page 28).
Bit 9 (512)
Reserved.
Bit 10 (1024)
Pointers are analyzed and more precise alias-information is generated (see
Section 3.4.14 [Alias Analysis], page 29). Using this information, better
data-flow analysis is possible.
Also, vbcc tries to place global/static variables and variables which have their
address taken in registers, if possible (see Section 3.4.1 [Register Allocation],
page 19).
Bit 11 (2048)
More aggressive loop optimizations are performed (see Section 3.4.10 [Loop Un-
rolling], page 24, and Section 3.4.9 [Induction Variable Elimination], page 23).
Only works if bit 5 (32) and bit 7 (128) are set.
Chapter 3: The Compiler 19
Bit 12 (4096)
Perform function inlining (see Section 3.4.11 [Function Inlining], page 26).
Bit 13 (8192)
Reserved.
Bit 14 (16384)
Perform inter-procedural analysis (see Section 3.4.15 [Inter-Procedural Analy-
sis], page 30) and cross-module optimizations (see Section 3.4.16 [Cross-Module
Optimizations], page 31).
Also look at the documentation for the target-dependent part of vbcc. There may be
additional machine specific optimization options.
Also, unused labels will be removed and basic blocks united to allow further optimizations.
For example, the following code
void f(int x, int y)
{
if(x > y)
goto label1;
q();
label1:
goto label2;
r();
label2:
}
will be optimized like:
void f(int x, int y)
{
if(x <= y)
q();
}
Identical code at the beginning or end of basic blocks will be moved to the
successors/predecessors under certain conditions.
tmp = x * y;
q(tmp, tmp);
}
Depending on the optimization level, vbcc will perform this optimization only locally within
basic blocks or globally across an entire function.
As this optimization requires detecting whether operand of an expression may have changed,
it will be affected by other optimizations. See Section 3.4.14 [Alias Analysis], page 29,
Section 3.4.15 [Inter-Procedural Analysis], page 30, and Section 3.4.16 [Cross-Module Op-
timizations], page 31.
Chapter 3: The Compiler 21
int f()
{
int x;
x = y;
return x;
}
will be optimized like:
int y;
int f()
{
return y;
}
Depending on the optimization level, vbcc will perform this optimization only locally within
basic blocks or globally across an entire function.
As this optimization requires detecting whether a variable may have changed, it will be
affected by other optimizations. See Section 3.4.14 [Alias Analysis], page 29, Section 3.4.15
[Inter-Procedural Analysis], page 30, and Section 3.4.16 [Cross-Module Optimizations],
page 31.
As this optimization requires detecting whether a variable may have changed, it will be
affected by other optimizations. See Section 3.4.14 [Alias Analysis], page 29, Section 3.4.15
[Inter-Procedural Analysis], page 30, and Section 3.4.16 [Cross-Module Optimizations],
page 31.
void f()
{
int y;
x = 1;
y = 2;
x = 3;
}
will be optimized like:
int x;
void f()
{
x = 3;
}
As this optimization requires detecting whether a variable may be read, it will be affected
by other optimizations. See Section 3.4.14 [Alias Analysis], page 29, Section 3.4.15 [Inter-
Procedural Analysis], page 30, and Section 3.4.16 [Cross-Module Optimizations], page 31.
{
int i;
}
As this optimization requires detecting whether operands of an expression may have
changed, it will be affected by other optimizations. See Section 3.4.14 [Alias Analysis],
page 29, Section 3.4.15 [Inter-Procedural Analysis], page 30, and Section 3.4.16
[Cross-Module Optimizations], page 31.
q(2);
q(3);
}
If the number of iteration is constant the loop will be unrolled as many times as permitted
by the size of the loop and -unroll-size. If the number of iterations is not a multiple of
the number of replications, the remaining iterations will be unrolled separately.
For example, the following code
void f()
{
int i;
i = 0;
tmp = n & 3;
26 vbcc manual
switch(tmp){
case 3:
q(i++);
case 2:
q(i++);
case 1:
q(i++);
}
while(i < n){
q(i++);
q(i++);
q(i++);
q(i++);
}
}
As this optimization requires detecting whether operands of an expression may have
changed, it will be affected by other optimizations. See Section 3.4.14 [Alias Analysis],
page 29, Section 3.4.15 [Inter-Procedural Analysis], page 30, and Section 3.4.16
[Cross-Module Optimizations], page 31.
{
return n + 1;
}
If a function to be inlined calls another function, that function can also be inlined. This
also includes a recursive call of the function.
int f(int n)
{
if(n < 2)
return 1;
else
return f(n - 1) + f(n - 2);
}
int f(int n)
{
if(n < 2)
return 1;
else{
int tmp1 = n - 1, tmp2, tmp3 = n - 2, tmp4;
if(tmp1 < 2)
tmp2 = 1;
else
tmp2 = f(tmp1 - 1) + f(tmp2 - 2);
if(tmp3 < 2)
tmp4 = 1;
else
tmp4 = f(tmp3 - 1) + f(tmp3 - 2);
return tmp2 + tmp4;
}
}
By default, only one level of inlining is done. The maximum nesting of inlining can be set
with -inline-depth. However, this option should be used with care. The code-size can
increase very fast and in many cases the code will be slower. Only use it for fine-tuning
after measuring if it is really beneficial.
28 vbcc manual
At lower optimization levels a function must be defined in the same translation-unit as the
caller to be inlined. With cross-module optimizations, vbcc will also inline functions which
are defined in other files. See Section 3.4.16 [Cross-Module Optimizations], page 31.
See also Section 3.5.3 [Inline-Assembly Functions], page 34.
function or from anywhere outside the program, interrupt-handlers or other data which
should be preserved. See Section 3.4.16 [Cross-Module Optimizations], page 31.
if(a < b)
p1 = &x[a];
else
p1 = &y[b];
p2 = &z[c];
...
}
As pointers itself may be aliased and function calls might modify pointers, this
analysis sometimes benefits from a larger scope of optimization. See Section 3.4.15
[Inter-Procedural Analysis], page 30, and Section 3.4.16 [Cross-Module Optimizations],
page 31.
This optimization will alter the behaviour of broken code which uses pointer arithmetic
to step from one object into another.
30 vbcc manual
− The 1999 C standard provides the restrict-qualifier to help alias analysis. If a pointer
is declared with this qualifier, the compiler may assume that the object pointed to by
this pointer is only aliased by pointers which are derived from this pointer. For a formal
definition of the rules for restrict please consult ISO/IEC9899:1999.
vbcc will make use of this information at higher optimization levels (-c99 must be used
to use this new keyword).
A very useful application for restrict are function parameters. Consider the following
example:
void cross_prod(float *restrict res,
float *restrict x,
float *restrict y)
{
res[0] = x[1] * y[2] - x[2] * y[1];
res[1] = x[2] * y[0] - x[0] * y[2];
res[2] = x[0] * y[1] - x[1] * y[0];
}
Without restrict, a compiler has to assume that writing the results through res can
modify the object pointed to by x and y. Therefore, the compiler has to reload all the
values on the right side twice. With restrict vbcc will optimize this code like:
void cross_prod(float *restrict res,
float *restrict x,
float *restrict y)
{
float x0 = x[0], x1 = x[1], x2 = x[2];
float y0 = y[0], y1 = x[1], y2 = y[2];
res[0] = x1 * y2 - x2 * y1;
res[1] = x2 * y0 - x0 * y2;
res[2] = x0 * y1 - x1 * y0;
}
close to each other. Also, instructions which depend on the result of another instruction
will be moved further apart to avoid pipeline-stalls.
Please note that it may be crucial to specify the correct derivate of a CPU family in order to
get best results from the sceduler. Different variants of an architecture may have a different
number and behaviour of pipelines requiring different scheduling decisions.
Consult the backend documentation for details.
− Missed break-points.
Setting break-points (especially on source-lines) needs some care when optimized code
is debugged. E.g. code may have been moved or even replicated at different parts.
A break-point set in a debugger will usually only be set on one instance of the code.
Therefore, a different instance of the code may have been executed although the break-
point was not hit.
3.5 Extensions
This section lists and describes all extensions to the C language provided by vbcc. Most
of them are implemented in a way which does not break correct C code and still allows all
diagnostics required by the C standard by using reserved identifiers.
The only exception (see Section 3.5.3 [Inline-Assembly Functions], page 34) can be turned
off using -iso or -ansi.
3.5.1 Pragmas
vbcc accepts the following #pragma-directives:
#pragma printflike <function>
#pragma scanflike <function>
vbcc will handle <function> specially. <function> has to be an already de-
clared function, with external linkage, that takes a variable number of argu-
ments and a const char * as the last fixed parameter.
If such a function is called with a string-constant as format-string, vbcc will
check if the arguments seem to match the format-specifiers in the format-string,
according to the rules of printf or scanf. Also, vbcc will replace the call by a
call to a simplified version according to the following rules, if such a function
has been declared with external linkage:
− If no format-specifiers are used at all, __v0<function> will be called.
− If no qualifiers are used and only d,i,x,X,o,s,c are used,
__v1<function> will be called.
− If no floating-point arguments are used, __v2<function> will be called.
#pragma dontwarn <n>
Disables warning number n. Must be followed by #pragma popwarn.
#pragma warn <n>
Enables warning number n. Must be followed by #pragma popwarn.
#pragma popwarn
Undoes the last modification done by #pragma warn or #pragma dontwarn.
#pragma only-inline on
The following functions will be parsed and are available for inlining (see
Section 3.4.11 [Function Inlining], page 26), but no out-of-line code will be
generated, even if some calls could not be inlined.
Do not use this with functions that have local static variables!
#pragma only-inline off
The following functions are translated as usual again.
34 vbcc manual
Example:
double sin(__reg("fp0") double) = "\tfsin.x\tfp0\n";
There are several issues to take care of when writing inline-assembly.
− As inline-assembly is subject to loop unrolling or function inlining it may be replicated
at different locations. Unless it is absolutely known that this will not happen, the code
should not define any labels (e.g. for branches). Use offsets instead.
− If a backend provides an instruction scheduler, inline-assembly code will also be sched-
uled. Some schedulers make assumptions about their input (usually compiler-generated
code) to improve the code. Have a look at the backend documentation to see if there
are any issues to consider.
− If a backend provides a peephole optimizer which optimizes the assembly output, inline-
assembly code will also be optimized unless -no-inline-peephole is specified. Have
a look at the backend documentation to see if there are any issues to consider.
− vbcc assumes that inline-assembly does not introduce any new control-flow edges. I.e.
control will only enter inline-assembly if the function call is reached and if control leaves
inline-assembly it will continue after the call.
Inline-assembly-functions are not recognized when ANSI/ISO mode is turned on.
3.5.6 __typeof
__typeof is syntactically equivalent to sizeof, but its result is of type int and is a number
representing the type of its argument. This may be necessary for implementing stdarg.h.
3.5.7 __alignof
__alignof is syntactically equivalent to sizeof, but its result is of type int and is the
alignment in bytes of the type of the argument. This may be necessary for implementing
stdarg.h.
3.5.8 __offsetof
__offsetof is a builtin version of the offsetof-macro as defined in the C language. The
first argument is a structure type and the second a member of the structure type. The
result will be a constant expression representing the offset of the specified member in the
structure.
read by the function. If a variable is read and written, both attributes have to be specified.
The variable-list is a list of identifiers, separated by slashes and enclosed in double quotes.
The attribute __writesmem(<type>) is used to specify that the function accesses memory
using a certain type. This is necessary if the function modifies memory accessible to the
calling function which cannot be specified using __varsmodified (e.g. because it is accessed
via pointers). __readsmem is similar, but specifies memory which is read.
If one of __varsused, varsmodified, __readsmem and __writesmem is specified, all relevant
side-effects must be specified. If, for example, only __varsused("my_global") is specified,
this implies that the function only reads my_global and does not modify any variable
accessible to the caller.
All of these attributes may be specified multiple times.
3.5.11 __noinline
__noinline will prevent inlining of a given function. The heuristic used for deciding whether
a function should be inlined generally makes a good trade-off between code size and perfor-
mance, but sometimes it can be useful to override this behaviour. Use-cases include keeping
"cold" functions out-of line to reduce code size, or to allow safe use of inline assembly with
labels.
3.7 Credits
All those who wrote parts of the vbcc distribution, made suggestions, answered my ques-
tions, tested vbcc, reported errors or were otherwise involved in the development of vbcc
(in descending alphabetical order, under work, not complete):
• Frank Wille
• Gary Watson
• Andrea Vallinotto
• Johnny Tevessen
• Eero Tamminen
• Gabriele Svelto
• Dirk Stoecker
• Ralph Schmidt
• Markus Schmidinger
• Thorsten Schaaps
Chapter 3: The Compiler 39
• Anton Rolls
• Michaela Pruess
• Thomas Pornin
• Joerg Plate
• Gilles Pirio
• Bartlomiej Pater
• Elena Novaretti
• Gunther Nikl
• Constantinos Nicolakakis
• Timm S. Mueller
• Robert Claus Mueller
• Joern Maass
• Aki M Laukkanen
• Kai Kohlmorgen
• Uwe Klinger
• Andreas Kleinert
• Julian Kinraid
• Acereda Macia Jorge
• Dirk Holtwick
• Matthew Hey
• Tim Hanson
• Kasper Graversen
• Jens Granseuer
• Volker Graf
• Marcus Geelnard
• Franta Fulin
• Matthias Fleischer
• Alexander Fichtner
• Olivier Fabre
• Robert Ennals
• Thomas Dorn
• Walter Doerwald
• Aaron Digulla
• Lars Dannenberg
• Sam Crow
• Michael Bode
• Michael Bauer
• Juergen Barthelmann
• Thomas Arnhold
40 vbcc manual
4 M68k/Coldfire Backend
This chapter documents the backend for the M68k and Coldfire processor families.
-no-fp-return
Do not return floats and doubles in floating-point registers even if code for an
fpu is generated.
-no-intz When generating code for FPU do quick&dirty conversions from floating-point
to integer. The code may be somewhat faster but will not correctly round to
zero. Only use it if you know what you are doing.
-no-mreg-return
Do not use multiple registers to return types that do not fit into a single register.
This is mainly for backwards compatibility with certain libraries.
-no-peephole
Do not perform peephole-optimizations.
-no-reserve-regs
Do not reserve temporary registers for the backend. Can lead to worse code
generation.
-old-softfloat
Use old libcall mechanism for software floating point. Should not be used, will
usually generate worse code.
-old-libcalls
Use old libcall mechanism for (some) integer support routines. Should not be
used, will usually generate worse code.
-phxass Generate assembly output for the PhxAss assembler.
-prof Insert code for profiling.
-sc Use small code model (see below).
-sd Use small data model (see below).
-use-commons
Use real common symbols instead of bss symbols for non-initialized external
variables.
-use-framepointer
By default automatic variables are addressed through a7 instead of a5. This
generates slightly better code, because the function entry and exit overhead is
reduced and a5 can be used as register variable etc.
However this may be a bit confusing when debugging and you can force vbcc
to use a5 as a fixed framepointer.
4.2 ABI
The current version generates assembler output for use with the vasmm68k_mot. Most
peephole optimizations are done by the assembler so vbcc only does some that the assembler
cannot make. The generated executables will probably only work with OS2.0 or higher.
With -gas assembler output suitable for the GNU assembler is generated (the version must
understand the Motorola syntax - some old ones do not). The output is only slightly
modified from the vasm-output and will therefore result in worse code on gas.
Chapter 4: M68k/Coldfire Backend 43
char 8 1
short 16 2
int 32 2
long 32 2
long long 64 2
all pointers 32 2
float(fpu) 32 2 see below
double(fpu) 64 2 see below
long double(fpu) 64 2 see below
The disadvantages are that one address register cannot be used by the compiler and that it
can only be used if all static data occupies less than 64kb. Also object modules and libraries
that have been compiled with different data models must not be mixed (it is possible to
call functions compiled with large data model from object files compiled with small data
model, but not vice versa and only functions can be called that way - other data cannot be
accessed).
If small data is used with functions which are called from functions which have not been
compiled with vbcc or without the small data model then those functions must be declared
with the __saveds attribute or call geta4() as the first statement (do not use automatic
initializations prior to the call to geta4). Note that geta4() must not be called through a
function pointer!
4.5 CPUs
The values of -cpu=n have those effects:
n<68000 Code for the Coldfire family is generated.
n>=68000 Code for the 68k family is generated.
n>=68020
− 32bit multiplication/division/modulo is done with the mul?.l, div?.l and
div?l.l instructions.
− tst.l ax is used.
− extb.l dx is used.
− 16/32bit offsets are used in certain addressing modes.
− link.l is used.
− Addressing modes with scaling are used.
n==68040
− 8bit constants are not copied in data registers.
− Static memory is not subject to common subexpression elimination.
4.6 FPUs
At the moment the values of -fpu=n have those effects:
n>68000 Floating point calculations are done using the FPU.
n=68040
n=68060 Instructions that have to be emulated on these FPUs will not be used; at the
moment this only includes the fintrz instruction in case of the 040.
Chapter 4: M68k/Coldfire Backend 45
4.7 Math
Long multiply on CPUs <68020 uses inline routines. This may increase code size a bit,
but it should be significantly faster, because function call overhead is not necessary. Long
division and modulo is handled by calls to library functions. (Some operations involving
constants (e.g. powers of two) are always implemented by more efficient inline code.)
If no FPU is specified floating point math is done using math libraries. 32bit IEEE format
is used for float and 64bit IEEE for double and long double.
If floating point math is done with the FPU floating point values are kept in registers and
therefore may have extended precision sometimes. This is not ANSI compliant but will
usually cause no harm. When floating point values are stored in memory they use the same
IEEE formats as without FPU. Return values are passed in fp0.
Note that you must not link object files together if they were not compiled with the same
-fpu settings and that a proper math library must be linked.
4.11 Stack
If the -stack-check option is used, every function-prologue will call the function __stack_
check with the stacksize needed by the current function on the stack. This function has to
consider its own stacksize and must restore all registers.
If the compiler is able to calculate the maximum stack-size of a function including all callees,
it will add a comment in the generated assembly-output (subject to change to labels).
4.12 Stdarg
A possible <stdarg.h> could look like this:
#endif
5 PowerPC Backend
This chapter documents the Backend for the PowerPC processor family.
5.2 ABI
This backend supports the following registers:
− r0 through r31 for the general purpose registers,
− f0 through f31 for the floating point registers and
− cr0 through cr7 for the condition-code registers.
Additionally, the register pairs r3/r4, r5/r6, r7/r8, r9/r10, r14/r15, r16/r17,
r18/r19, r20/r21, r22/r23, r24/r25, r26/r27, r28/r29 and r30/r31 are available.
r0, r11, r12, f0, f12 and f13 are reserved by the backend.
The current version generates assembly output for use with vasmppc or the GNU assembler.
The generated code should work on 32bit systems based on a PowerPC CPU using the V.4
ABI or the PowerPC Embedded ABI (eabi).
Chapter 5: PowerPC Backend 51
The registers r0, r3-r12, f0-f13 and cr0-cr1 are used as scratch registers (i.e. they can be
destroyed in function calls), all other registers are preserved. r1 is the stack-pointer and r13
is the small-data-pointer if small-data-mode is used.
The first 8 function arguments which have integer or pointer types are passed in registers
r3 through r10 and the first 8 floating-point arguments are passed in registers f1 through
f8. All other arguments are passed on the stack.
Integers and pointers are returned in r3 (and r4 for long long), floats and doubles in f1.
All other types are returned by passing the function the address of the result as a hidden
argument - so when you call such a function without a proper declaration in scope you can
expect a crash.
The elementary data types are represented like:
type size in bits alignment in bytes (-amiga-align)
char 8 1 (1)
short 16 2 (2)
int 32 4 (2)
long 32 4 (2)
long long 64 8 (2)
all pointers 32 4 (2)
float 32 4 (2)
double 64 8 (2)
5.6 Stack
If the -stack-check option is used, every function-prologue will call the function __stack_
check with the stacksize needed by this function in register r12. This function has to
consider its own stacksize and must restore all registers.
5.7 Stdarg
A possible <stdarg.h> for V.4 ABI could look like this:
typedef struct {
int gpr;
int fpr;
char *regbase;
char *membase;
} va_list;
char *__va_start(void);
char *__va_regbase(void);
int __va_fixedgpr(void);
int __va_fixedfpr(void);
#define va_start(vl,dummy) \
( \
vl.gpr=__va_fixedgpr(), \
vl.fpr=__va_fixedfpr(), \
vl.regbase=__va_regbase(), \
vl.membase=__va_start() \
)
Chapter 5: PowerPC Backend 53
#define va_arg(vl,type) \
( \
(__typeof(type)&127)>10? \
__va_mem((vl),type) \
: \
( \
(((__typeof(type)&127)>=6&&(__typeof(type)&127)<=8)) ? \
( \
++(vl).fpr<=8 ? \
((type*)((vl).regbase+32))[(vl).fpr-1] \
: \
__va_mem((vl),type) \
) \
: \
( \
++(vl).gpr<=8 ? \
((type*)((vl).regbase+0))[(vl).gpr-1] \
: \
__va_mem((vl),type) \
) \
) \
)
6.2 ABI
This backend supports the following registers:
− $0 through $31 for the general purpose registers and
− $f0 through $f31 for the floating point registers.
The current version generates assembly output for use with the GNU assembler. The
generated code should work on systems with 21064, 21066, 21164 and higher Alpha CPUs.
The registers $0-$8, $16-$28, $f0, $f1 and $f10-$f30 are used as scratch registers (i.e.
they can be destroyed in function calls), all other registers are preserved. Of course $31
and $f31 cannot be used.
The first 6 function arguments which have arithmetic or pointer types are passed in registers
$16/$f16 through $21/$f21.
Integers and pointers are returned in $0, floats and doubles in $f0. All other types are
returned by passing the function the address of the result as a hidden argument - so when
you call such a function without a proper declaration in scope you can expect a crash.
The elementary data types are represented like:
type size in bits alignment in bytes
char 8 1
short 16 2
int 32 4
long 64 8
56 vbcc manual
long long 64 8
all pointers 64 8
float 32 4
double 64 8
6.4 Stdarg
A possible <stdarg.h> could look like this:
typedef struct {
char *regbase;
char *membase;
int arg;
} va_list;
char *__va_start(void);
int __va_fixargs(void);
#define va_start(vl,dummy) \
(vl.arg=__va_fixargs(),vl.regbase=__va_start(),vl.membase=vl.regbase+(6-vl.arg)*16)
7 i386 Backend
This chapter documents the Backend for the Intel i386 processor family.
7.2 ABI
This backend supports the following registers:
− %eax, %ebx, %ecx, %edx
− %esi, %edi, %ebp, %esp
(And %st(0)-%st(7) for the floating point stack but these must not bes used for register
variables because they cannot be handled like normal registers.)
The current version generates assembly output for use with the GNU assembler. The
generated code should work on systems with Intel 80386 or higher CPUs with FPU and
compatible chips.
The registers %eax, %ecx and %edx (as well as the floating point stack) are used as scratch
registers (i.e. they can be destroyed in function calls), all other registers are preserved.
All elementary types up to 4 bytes are returned in register %eax Floating point values are
returned in %st(0). All other types are returned by passing the function the address of the
result as a hidden argument - so when you call such a function without a proper declaration
in scope you can expect a crash.
60 vbcc manual
vbcc uses %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp and the floating point stack for
temporary results and register variables. Local variables are created on the stack and
addressed via %esp.
The elementary data types are represented like:
type size in bits alignment in bytes (-longalign)
char 8 1 (1)
short 16 2 (4)
int 32 2 (4)
long 32 2 (4)
long long n/a n/a
all pointers 32 2 (4)
float 32 2 (4)
double 64 2 (4)
7.4 Stdarg
A possible <stdarg.h> could look like this:
typedef unsigned char *va_list;
8 c16x Backend
This chapter documents the Backend for the c16x/st10 microcontroller family.
8.2 ABI
This backend supports the following registers:
− R0 through R15 for the general purpose registers
Additionally, the register pairs R2/R3, R3/R4, R4/R5, R6/R7, R7/R8, R8/R9, R12/R13,
R13/R14, and R15/R15 are available.
R1, R11 and R12 are reserved by the backend.
The current version generates assembly output for use with the vasm assembler. Option-
ally, assembly code for the Tasking assembler can be generated. The default memory
62 vbcc manual
model corresponds to the Tasking small-memory model with 16bit data-pointers and 32bit
function-pointers. However, the DPPx registers have to be set up in a way to create a linear
16bit address space (i.e. DPPx=x). The generated code should work on systems with c161,
c163, c164, c165 and c167 microcontrollers as well as ST10 derivates. Old versions like the
c166 are not supported
The registers R1-R5 and R10-R15 are used as scratch registers (i.e. they can be destroyed
in function calls), all other registers are preserved.
R0 is used as user stack pointer. Automatic variables and temporaries are put on the user
stack. Return addresses are pushed on the system stack.
The first 4 function arguments which have integer or pointer types are passed in registers
R12 through R15.
Integers and pointers are returned in R4/R5. All other types are returned by passing the
function the address of the result as a hidden argument - so when you call such a function
without a proper declaration in scope you can expect a crash.
The elementary data types are represented like:
type size in bits alignment in bytes
char 8 1
short 16 2
int 16 2
long 32 2
long long n/a n/a
near pointers 16 2
far pointers 32 2
huge pointers 32 2
float n/a n/a
double n/a n/a
__esfr(<addr>)
The same for extended special function registers.
__sfrbit(<addr>,<bit>)
Declare a single bit in the bit-addressable area.
Example:
__sfr(0xff10,11) volatile __bit IEN;
__esfrbit(<addr>,<bit>)
The same for the extended bit-addressable area.
8.7 Stack
If the -stack-check option is used, every function-prologue will call the function __stack_
check with the stacksize needed by this function in register R1. This function has to consider
its own stacksize and must restore all registers.
Only stack-checking of the user-stack is supported. Checking the system-stack is supported
by hardware.
8.8 Stdarg
A possible <stdarg.h> could look like this:
typedef char *va_list;
va_list __va_start(void);
#define __va_rounded_size(__TYPE) \
(((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
9 68hc12 Backend
This chapter documents the Backend for the 68hc12 and 6809/6309 microcontroller families.
9.2 ABI
The current version generates assembly output for use with vasm6809 std or the GNU
assembler using the non-banked model.
This backend supports the following registers:
− d for the accumulator (also used for byte, i.e. b)
66 vbcc manual
The accumulator and x are caller-save. The y register is callee-save. The u register is used
as data-page pointer with -drel.
The first function argument which has integer or pointer type up to 16 bits is passed in the
accumulator d. The remaining arguments are passed on the stack.
Integers and pointers are returned in d or d/x (x contains the higher bits). All other types
are returned by passing the function the address of the result as a hidden argument - so
when you call such a function without a proper declaration in scope you can expect a crash.
The elementary data types are represented like:
type size in bits alignment in bytes
char 8 1
short 16 1
int 16 1
long 32 1
near pointers 16 1
far pointers 24 1 (not yet)
huge pointers 24 1 (not yet)
float 32 1 (not yet)
double 64 1 (not yet)
long double 64 1 (not yet)
__interrupt
Return with rti rather than rts.
__section("name","attr")
Place this function/object in section "section" with attributes "attr".
__dpage Place the variable in section .dpage and use direct addressing.
9.5 Stack
If the -stack-check option is used, every function-prologue will call the function __stack_
check with the stacksize needed by this function in register y. This function has to consider
its own stacksize and must restore all registers.
9.6 Stdarg
Stdarg is supported by the provided include.
10 VideoCore IV Backend
This chapter documents the Backend for the VideoCore IV processor family.
The backend is in a very early stage, it is not complete, and it can not yet be considered
useful!
Also note that it is based on freely available, unofficial, and possibly incorrect information
on the target processor.
10.2 ABI
This backend supports the following registers:
− r0 through r31 for the general purpose registers
Additionally, the register pairs r0/r1 r2/r3, r4/r5, r6/r7, r8/r9, r10/r11, r12/r13,
r14/r15, r16/r17, r18/r19, r20/r21, r22/r23 are available.
r14, r15, r24-r31 are currently reserved by the backend.
The current version generates assembly output for use with vasm.
The registers r0-r5 and r14-r15 are used as scratch registers (i.e. they can be destroyed in
function calls), all other registers are preserved. r25 is the stack-pointer.
The first 6 function arguments which have integer, float32 or pointer types are passed in
registers r0 through r5. All other arguments are passed on the stack.
70 vbcc manual
Integers, float32 and pointers are returned in r0. All other types are returned by passing the
function the address of the result as a hidden argument - so when you call such a function
without a proper declaration in scope you can expect a crash.
The elementary data types are represented like:
type size in bits alignment in bytes
char 8 1
short 16 2
int 32 4
long 32 4
long long 64 8 not yet supported
all pointers 32 4
float 32 4
double 64 (32) 4
long double 64 (32) 4
10.6 Stdarg
stdarg-implementation is not yet fully working. One restriction is that when calling a
varargs function, the prototype must be in scope (this is ISO C conforming). Another one
is that the stdarg-macros only work as long as all fixed arguments are passed in registers.
This will be fixed in the future.
11 6502 Backend
This chapter documents the backend for the 6502 processor family.
-common-banknr=<n>
Specify the bank number of the common bank. See chapter on banking. The
default number is 0.
-large Use large memory model. All pointers will be far pointers. A corresponding
library is required. This feature is experimental.
-glob-acc
By default, the register allocator will only assign temporary variables to the
accumulator register or a/x register pair. Usually this reduces necessary stor-
ing/loading of the accumulator as it is needed during most operations. This
option allows the register allocator to assign variables with bigger live ranges
to the accumulator. This option is likely to create worse code in most cases.
Use only for experimentation.
11.2 ABI
The current version generates assembler output for use with vasm6502_oldstyle or
vasm6502_std. The option -opt-branch is needed.
The register names provided by this backend are:
a, sp, r0..r31, btmp0..btmp3
a is the accumulator. It can be used for type char.
r0 ... r31 are 8bit variables that can be used for type char. They have to be mapped to
zero page during linking. The compiler expects registers that can be used as register pairs
(see below) to be mapped to contiguous memory locations. Some library routines may have
additional requirements.
sp is a 16bit variable that has to be mapped to zero page. It is used by the compiler and not
available for use. sp must be initialized to a suitable memory area. This stack is used for
local variables, saved registers etc. The hardware stack is used mainly for return addresses
and sometimes saved registers.
btmp0..btmp3 are 32bit variables. The code generated by vbcc does not require them in
zero page, but the current library implementation expects them to be located to contiguous
zero page locations.
The following register pairs can be used for 16bit values.
a/x, r0/r1, r2/r3 ... r30/r31
a/x can be used for types short and int, the other register pairs can also be used for
pointer types.
The following register pairs can be used for 64bit values (IEEE doubles or long long).
btmp0/btmp1, btmp2/btmp3
Registers a, r0..r15, r28..r31, btmp0..btmp3 are volatile (i.e. they can be destroyed in
function calls). r16..r27 are preserved across function calls.
r0..r7 are used for passing function arguments of type char, short, int and pointer
types. btmp0..btmp3 are used for passing arguments of type long, long long, float,
double, long double and far pointers. All other types are passed on the stack.
Chapter 11: 6502 Backend 75
For functions with a variable-argument-list, arguments that are part of the variable-
argument-list are always passed on the stack. It is therefore required that a prototype is
in scope when calling such functions (as required by C).
Scalar types are returned as follows:
type registers
char a
short a/x
int a/x
long btmp0
long long n/a
pointers a/x
far-pointer btmp0
float btmp0
double btmp0 or btmp0/btmp1 (IEEE)
long double btmp0 or btmp0/btmp1 (IEEE)
All other types are returned by passing the function the address of the result as a hidden
argument - such a function must not be called without a proper declaration in scope.
The basic data types are represented like this:
type size in bits alignment in bytes
char 8 1
short 16 1
int 16 1
long 32 1
long long 64 1 (currently not supported)
near pointers 16 1
far pointers 24 1
float 32 1 see below
double 32/64 1 see below
long double 32/64 1 see below
11.3 Math
For certain operations vbcc will emit calls to routines that have to be provided by a library.
For integer code, the following operations are handled by library routines (some special
cases involving constants may be handled by inline code).
__mulint16 16x16=>16 multiplication
__mulint32 32x32=>32 multiplication
__divint16 16x16=>16 signed division
__divint32 32x32=>32 signed division
__divuint16 16x16=>16 unsigned division
__divuint32 32x32=>32 unsigned division
__modint16 16x16=>16 signed modulo
__modint32 32x32=>32 signed modulo
__moduint16 16x16=>16 unsigned modulo
76 vbcc manual
__nocpr Turn off code compression for this function even if -size is used. Useful for
time-critical functions.
__bank(<n>)
Place the variable/function in bank n. See chapter on banking for details.
11.7 Stack
Local variables and function arguments are put on the user stack. It can be up to 64KB,
but accessing variables outside the lower 256 bytes is significantly slower. vbcc will put
small variables on lower offsets to increase the number of variables that can be addressed
fast. However, accessing the stack is always rather slow on the 6502.
The stack pointer is adjusted once during function entry/exit to avoid multiple costly ad-
justments to the stack pointer.
Variable-length-arrays as specified in c99 should be fully supported.
11.8 Banking
Many 6502 systems offer/need different banking mechanisms. vbcc offers different levels of
support for those schemes. Depending on the target integration, more or less support is
offered.
For manual banking, functions and/or data can be mapped to sections using the section
attribute or the #pragma section directive. Note that string constants will be mapped to
banked memory only when using the #pragma approach.
After placing the objects in suitable sections, they have to be located using a linker command
file. See the documentation on vlink. Switching between banks has to done manually in a
system-specific way.
If initialized variables are mapped into banked sections, be aware that you may have to
provide means to initialize them on startup. It is probably not handled by startup code for
non-banked systems. This is not relevant for systems that only provide banked ROM.
11.8.2.2 Mapping
Code/data can be put into banks using the bank-attribute or #pragma bank. Note that
string constants will be mapped to banked memory only when using the #pragma approach.
Code/data not mapped to a bank will be mapped to the always visible non-banked area.
Banked objects will be mapped to sections suffixed with the bank number, e.g. in
__bank(0) int i = 1;
__bank(1) void f()
i will be put into section data0 and f will be put into section text1.
__bank(0) i0;
__bank(1) i1;
__far int *fp;
...
if(..)
fp = &i0;
else
fp = &i1;
Converting a far-pointer to a normal pointer will loose the bank information. Converting a
normal pointer to a far-pointer will insert the bank number of the current function. Care
must be taken not to loose bank information when working with pointers.
11.8.2.6 Library
To use the automated bank switching, a series of library functions must be available (TODO:
add more detailed information, may change):
___bankswitch
Make the bank in y accessible.
___bankjsr
Call the function pointer r30/r31 in bank y. Return to the caller in bank a.
___bankload<n> (n=1,2,3,4,8)
Copy <n> bytes from r30/r31 in bank y to non-banked variable ___bankv with
offset x. Caller bank in a.
80 vbcc manual
___bankstore<n> (n=1,2,3,4,8)
Copy <n> bytes from non-banked variable ___bankv with offset x to r30/r31
in bank y. Caller bank in a.
___bankcopy
Copy ___bankcopy_len/___bankcopy_len+1 bytes from r28/r29 in bank y to
r30/r31 in bank x. Caller bank in a.
11.9 Debugging
The 6502 backend has some limited support for debugging.
When using vlink, the -vicelabels options can be used to output symbol values in a
format that can be read by the vice emulator/debugger.
With the -g option, line numbers and file names of source code will be added to the
assembly output. Using some tools, it should be possible to create a mixed C/assembly
file for inspection. Depending on the optimization level, the results may be more or less
usable, see section Debugging Optimized Code. Note that the added comments will affect
the assembly peephole optimizer, resulting in worse code than without -g.
12 Instruction Scheduler
vsc - scheduler for vbcc (c) in 1997-99 by Volker Barthelmann
12.1 Introduction
vsc is an instruction-scheduler which reorders the assembly output of vbcc and tries to
improve performance of the generated code by avoiding pipeline stalls etc.
Like the compiler vbcc it is split into a target independent and a target dependent part.
However there may be code-generators for vbcc which do not have a corresponding scheduler.
This document only deals with the target independent parts of vsc. Be sure to read all the
documents for your machine.
12.2 Usage
Usually vsc will be called by a frontend. However if you call it directly, it has to be done
like this:
vsc [options] input-file output-file
The following options are supported:
-quiet Do not print the copyright notice.
-debug=<n>
Set debug-level to <n>.
Note that depending on the target vbcc may insert hints into the generated code to tell
vsc what CPU to schedule for. Code scheduled for a certain CPU may run much slower on
slightly different CPUs. Therefore it is especially important to specify the correct target-
CPU when compiling.
13 Code Compressor
vcpr - code compressor for vbcc (c) in 2020 by Volker Barthelmann
13.1 Introduction
vcpr is a code compressor which scans the assembly output of vbcc and tries to reduce code
size of the generated code by moving common code sequences into separate subroutines. As
a trade-off, the code will usually run slower.
Like the compiler vbcc it is split into a target independent and a target dependent part.
However there may be code-generators for vbcc which do not have a corresponding com-
pressor.
This document only deals with the target independent parts of vcpr. Be sure to read all
the documents for your machine.
13.2 Usage
Usually vcpr will be called by a frontend. However if you call it directly, it has to be done
like this:
vcpr [options] input-file output-file
The following options are supported:
-quiet Do not print the copyright notice.
-debug=<n>
Set debug-level to <n>.
Note that depending on the target vbcc may insert hints into the generated code. Assembly
code that was not generated by vbcc may not work correctly after running it through vcpr.
Lines have to be textually identical to be considered for outlining. One exception are labels.
The following sequences are considered equal as long as the labels are not used anywhere
else:
a
bne l1
b
l1:
c
a
bne l2
b
l2:
c
Currently, vcpr only supports code sequences with one label.
14 C Library
This chapter describes the C library usually provided with vbcc.
14.1 Introduction
To execute code compiled by vbcc, a library is needed. It provides basic interfaces to the
underlying operating system or hardware as well as a set of often used functions.
A big part of the library is portable across all architectures. However, some functions (e.g.
for input/output or memory allocation) are naturally dependent on the operating system
or hardware. There are several sections in this chapter dealing with different versions of the
library.
The library itself often is split into several parts. A startup-code will do useful initializations,
like setting up IO, parsing the command line or initializing variables and hardware.
The biggest part of the functions will usually be stored in one library file. The name and
format of this file depends on the conventions of the underlying system (e.g. vc.lib or
libvc.a).
Often, floating point code (if available) is stored in a different file (e.g. m.lib or libm.a).
If floating point is used in an application, it might be necessary to explicitly link with this
library (e.g. by specifying -lm).
In many cases, the include files provide special inline-code or similar optimizations. There-
fore, it is recommended to always include the corresponding include file when using a library
function. Even if it is not necessary in all cases, it may affect the quality of the generated
code.
The library implements the functions specified by ISO9899:1989 as well as a part of the new
functions from ISO9899:1999.
14.2 Legal
Most parts of this library are public domain. However, for some systems, parts may be
under a different license. Please consult the system specific documentation. Usually, linking
against this library will not put any restrictions on the created executable unless otherwise
mentioned.
Parts of the math library (e.g. transcendental functions) are derived from Sun’s free math
library:
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
The softfloat functions, used by some targets, are derived from John Hauser’s IEC/IEEE
Floating-point Artithmetic Package:
This C source file is part of the SoftFloat IEC/IEEE Floating-point
88 vbcc manual
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the web page ‘http://HTTP.CS.Berkeley.EDU/~jhauser/
arithmetic/softfloat.html’.
14.4.1 Startup
The startup is usually split into two parts. The first part is done by assembly code that
produces the object file lib/startup.o. This assembly code is usually provided with vbcc
and may have to be adapted to the hardware you are using. The key actions that have to
be performed by this code are:
Chapter 14: C Library 89
−hardware initialization
It may be necessary to perform some hardware initialization right at the be-
ginning, e.g. to configure the memory system. This has to be modified by the
user.
−variable initializations
When running code from ROM, some memory sections have to be initialized.
Usually, the init-values of initialized variables have to be copied from ROM to
the data segment and the values of un-initialized variables have to be cleared
in the bss segment. This code is usually provided in the startup code.
−stack pointer
The stack pointer has to be set to a suitable memory area. The startup code
will set the stack pointer to the value of the pointer __stack. There is a default
stack provided in the C library which will be used unless the application defines
its own stack using, for example, the following code (assuming that the stack
grows downwards):
#define STACKSIZE <whatever>
14.4.2 Heap
When dynamic memory management is used (e.g. by using the malloc() function), a heap
memory area is needed to allocate memory from. The malloc() function assumes that __
heapptr is a variable pointing to the beginning of the heap memory and that __heapsize
specifies the size of the heap area in bytes. The library will provide a default heap memory
area that can be replaced by adding, for example, the following file to the application:
#define HEAPSIZE <whatever>
char __heap[HEAPSIZE],*__heapptr=__heap;
size_t __heapsize=HEAPSIZE;
14.4.3 Input/Output
The standard C input/output functions are provided also for embedded systems. Read-
ing/writing to a stream will be directed to void unless the following low-level I/O-functions
are provided by the application:
int __open(const char *name,const char *mode);
void __close(int h);
size_t __read(int h,char *p,size_t l);
90 vbcc manual
14.4.7 Linking/Locating
To produce ROM images (e.g. in the form of absolute ELF executables, Intel Hex files
or Motorola S-Records), the linker is called with a linker script. This script can be used
to join together different sections of the input files and locate them to suitable absolute
memory areas. Also, this linker script can be used to set symbols that may be used by the
application or the startup code, e.g. addresses of data sections, initialization values or small
data pointers.
Code or data that has to reside at special locations can be put into a special section using
the __section attribute. This section can then be placed at the desired location using the
linker script.
Usually, an example linker script will be provided. While this is often not suitable for
different chips, it may serve as a starting point.
Chapter 14: C Library 91
14.5 AmigaOS/68k
This section describes specifics of the C library for AmigaOS/68k provided by the
target m68k-amigaos. The relevant files are startup.o, minstart.o, minres.o,
vc.lib, vcs.lib, mieee.lib, mieees.lib, m881.lib, m881s.lib, m040.lib, m040s.lib,
m060.lib, m060s.lib, msoft.lib, msofts.lib, amiga.lib, amigas.lib, auto.lib and
autos.lib, reaction.lib, reactions.lib.
Note that extra.lib is no longer part of the vbcc distribution. It was replaced by
’PosixLib’, available on Aminet dev/c/vbcc_PosixLib.lha, which has a much more com-
prehensive support for POSIX and Unix functions.
The following config files are available:
aos68k Standard startup code (startup.o) with command line parsing and optional
Workbench startup (See Section 14.5.1 [Standard Startup], page 91).
aos68km Minimal startup code (minstart.o) without command line parsing. You have
to open all libraries yourself (See Section 14.5.6 [Minimal Startup], page 93).
aos68kr Minimal startup code (minres.o) for resident programs. Always compiles in
small data mode and links with vcs.lib (See Section 14.5.7 [Minimal Resident],
page 94).
14.5.1 Startup
The startup code currently consists of a slightly modified standard Amiga startup
(startup.o). The startup code sets up some global variables and initializes stdin, stdout
and stderr. The exit code closes all open files and frees all memory. If you link with a
math library the startup/exit code will be taken from there if necessary.
when your config file contains -amiga-softfloat (which is the case for aos68k
since vbcc V0.9h).
m881.lib This one uses direct FPU instructions and function return values are passed in
fp0. You must have a 68020 or higher and an FPU to use this library. You
also have to specify -fpu=68881 or -fpu=68882. Several FPU instructions that
have to be emulated on 040/060 may be used.
m040.lib This one uses only direct FPU instructions that do not have to be emulated on
a 68040. Other functions use the Motorola emulation routines modified by Aki
M Laukkanen and Matthew Hey. It should be used for programs compiled for
68040 with FPU. Return values are passed in fp0.
m060.lib This one uses only direct FPU instructions that do not have to be emulated on
a 68060. Other functions use the Motorola emulation routines modified by Aki
M Laukkanen and Matthew Hey. It should be used for programs compiled for
68060 with FPU. Return values are passed in fp0.
Depending on the CPU/FPU selected, including math.h will cause inline-code generated
for certain math functions.
14.5.3 Stack
An application can specify the stack-size needed by defining a variable __stack (of type
size_t) with external linkage, e.g.
size_t __stack=65536; /* 64KB stack-size */
The startup code will check whether the stack-size specified is larger than the default stack-
size (as set in the shell) and switch to a new stack of appropriate size, if necessary.
If the -stack-check option is specified when compiling, the library will check for a stack
overflow and abort the program, if the stack overflows. Note, however, that only code
compiled with this option will be checked. Calls to libraries which have not been compiled
with -stack-check or calls to OS function may cause a stack overflow which is not noticed.
Additionally, if -stack-check is used, the maximum stack-size used can be read by querying
the external variable __stack_usage.
#include <stdio.h>
main()
{
do_program();
printf("stack used: %lu\n",(unsigned long)__stack_usage);
}
Like above, the stack used by functions not compiled using -stack-check or OS functions
is ignored.
Chapter 14: C Library 93
14.5.5 Restrictions
The following list contains some restrictions of this version of the library:
tmpfile()
The tmpfile() function always returns an error.
clock() The clock() function always returns -1. This is correct, according to the C
standard, because on AmigaOS it is not possible to obtain the time used by the
calling process.
int main()
{
if(DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",0)){
Write(Output(),"Hello, world!\n",14);
CloseLibrary((struct Library *)DOSBase);
}
return 0;
94 vbcc manual
This can yield an executable of under 256 bytes when compiled with -sc -sd and linked
with minstart.o and amigas.lib (using vlink - may not work with other linkers).
14.5.8 amiga.lib
To write programs using AmigaOS (rather than standard C functions only), a replacement
for the original (copyrighted) amiga.lib is provided with vbcc. This replacement is adapted
to vbcc, does not cause collisions with some functions (e.g. sprintf) provided by the
original amiga.lib and is available for the small data mode as well. It is recommended to
always use this library rather than the original version.
Additionally, there are header files (in the proto- and inline-subdirectories) which cause
inlined calls to Amiga library functions.
Besides some support functions amiga.lib contains stub routines to call functions from
all common AmigaOS libraries with stack arguments. By including the library’s proto
header file you make sure that AmigaOS functions are called directly by inline code, unless
_NO_INLINE is defined.
Preprocessor defines to control the behaviour of vbcc’s proto headers:
__NOLIBBASE__
Do not declare the library base symbol.
_NO_INLINE
Do not use optimized inline code for library function calls.
Note that the OS-call inlines have been generated using the NDK3.2 clib header files, while
trying to keep compatibility to NDK3.9, so it is advised to use one of the two NDKs for
development. Otherwise you will get warnings about missing CONST typedefs and similar.
Chapter 14: C Library 95
14.5.9 auto.lib
To link with auto.lib (or the small data version autos.lib) specify the -lauto or -lautos
option to vc.
When you are calling a standard Amiga library function without having defined the corre-
sponding library base, then the library base as well as code to open/close it will be taken
from auto.lib.
By default, auto.lib will try to open any library version. If you need at least a certain
version you can define and set a variable <library-base>Ver with external linkage, e.g. (on
file-scope):
int _IntuitionBaseVer = 39;
Note that your program will abort before reaching main() if one of the libraries cannot
be opened. Also note that auto.lib depends on constructor/destructor handling in vclib,
which means it cannot work when linking without vclib, without standard startup code, or
only with a minimal startup code, like minstart.o.
14.5.10 reaction.lib
The reaction.lib in vbcc is a port of Stephan Rupprecht’s rewrite of the copyrighted
linker library, extended and fixed by Olaf Barthel for the NDK 3.2 release. This version
should work in combination with NDK 3.9 as well.
To link with reaction.lib (or the small data version reactions.lib) specify the
-lreaction or -lreactions option to vc.
The library contains ReAction GUI class support functions and their autoinitialization
code. Refer to reaction_lib.doc from your NDK Autodocs for more information. As
documented there, the version used to automatically open the classes can be defined by
the variable __reactionversion with external linkage. Otherwise a default of version 0 is
used.
14.6 Kickstart1.x/68k
This section describes specifics of the C library for Amiga Kickstart 1.2 and 1.3 provided
by the target m68k-kick13. The relevant files are startup.o, minstart.o, minres.o,
startup16.o, minstart16.o, minres16.o, vc.lib, vcs.lib, m13.lib, m13s.lib,
msoft.lib, msofts.lib, m881.lib, m881s.lib, amiga.lib, amigas.lib, auto.lib and
autos.lib, vc16.lib, vc16s.lib, m1316.lib, m1316s.lib, msoft16.lib, msoft16s.lib,
m88116.lib, m88116s.lib, amiga16.lib, amiga16s.lib, auto16.lib and auto16s.lib.
This target makes it possible to develop programs targeted for these older versions of the
Amiga operating system, using the original Commodore Kickstart 1.3 header files. Note
that there are also libraries and config files for using a 16-bit int ABI, which was common
at that time, and may have some advantages on 16-bit CPUs, like the 68000 or 68010.
The following config files are available:
kick13 Standard startup code (startup.o) with command line parsing and optional
Workbench startup (See Section 14.6.1 [Startup13], page 96) using 32-bit int.
96 vbcc manual
kick13m Minimal startup code (minstart.o) without command line parsing. You have
to open all libraries yourself (See Section 14.5.6 [Minimal Startup], page 93)
using 32-bit int.
kick13r Minimal startup code (minres.o) for resident programs. Always compiles in
small data mode and links with vcs.lib (See Section 14.5.7 [Minimal Resident],
page 94) using 32-bit int.
kick13s Standard startup code (startup.o) with command line parsing and optional
Workbench startup (See Section 14.6.1 [Startup13], page 96) using 16-bit int.
kick13sm Minimal startup code (minstart.o) without command line parsing. You have
to open all libraries yourself (See Section 14.5.6 [Minimal Startup], page 93)
using 16-bit int.
kick13sr Minimal startup code (minres.o) for resident programs. Always compiles in
small data mode and links with vcs.lib (See Section 14.5.7 [Minimal Resident],
page 94) using 16-bit int.
14.6.1 Startup
The startup code currently consists of a slightly modified standard AmigaOS 1.3 startup
(startup.o). The startup code sets up some global variables and initializes stdin, stdout
and stderr. The exit code closes all open files and frees all memory. If you link with a math
library the startup/exit code will be taken from there if necessary.
m13.lib This one uses the C= math libraries present under Kickstart 1.2 and 1.3. The
startup code will always open mathffp.library, MathIeeeDoubBas.library and
MathIeeeDoubTrans.library. Note that all single precision floating point calcu-
lations take place in FFP format and have to be converted between FFP and
IEEE by the library. Float return values are passed in d0, double return values
are passed in d0/d1. A 68000 is sufficient to use this library. You must not
specify -fpu=... when you use this library.
msoft.lib
This one is based on John Hauser’s IEC/IEEE Floating-point Arithmetic Pack-
age (See Section 14.3 [SoftfloatHauser], page 88) and doesn’t need any system
libraries for FP emulation. May be slower than the ROM libraries, though.
Otherwise everything mentioned for m13.lib applies here as well.
m881.lib This one uses direct FPU instructions and function return values are passed in
fp0. You must have a 68020 or higher and an FPU to use this library. You
also have to specify -fpu=68881. Several FPU instructions that have to be
emulated on 040/060 may be used.
Chapter 14: C Library 97
14.6.3 Stack
Stack-checking is available similar to AmigaOS/68k (See Section 14.5.3 [amiga-stack],
page 92). But there is no automatic stack-extension under Kickstart 1.3 and a __stack
variable will be ignored.
14.6.5 Restrictions
The following list contains some restrictions of this version of the library:
tmpfile()
The tmpfile() function always returns an error.
clock() The clock() function always returns -1. This is correct, according to the C
standard, because on AmigaOS it is not possible to obtain the time used by the
calling process.
14.6.6 amiga.lib
See Section 14.5.8 [amigalib], page 94.
This version of amiga.lib only supports the functionality present in Kickstart 1.2/1.3.
14.6.7 auto.lib
This library corresponds to the AmigaOS/68k version (See Section 14.5.9 [autolib], page 95),
but only supports libraries of Kickstart 1.3.
14.7 PowerUp/PPC
This section describes specifics of the C library for PowerUp/PPC provided by the target
ppc-powerup. The relevant files are startup.o, minstart.o, libvc.a, libvcs.a, libm.a,
libms.a libamiga.a, libamigas.a, libauto.a and libautos.a.
Note that libextra.a is no longer part of the vbcc distribution. It was replaced by
’PosixLib’, available on Aminet dev/c/vbcc_PosixLib.lha, which has a much more com-
prehensive support for POSIX and Unix functions.
98 vbcc manual
14.7.1 Startup
The startup code startup.o sets up some global variables and initializes stdin, stdout and
stderr. The exit code closes all open files and frees all memory. If you link with a math
library the startup/exit code will be taken from there if necessary.
14.7.3 Stack
Stack-handling is similar to AmigaOS/68k (See Section 14.5.3 [amiga-stack], page 92). The
only difference is that stack-swapping cannot be done. If the default stack-size is less than
the stack-size specified with __stack the program will abort.
14.7.5 Restrictions
The following list contains some restrictions of this version of the library:
tmpfile()
The tmpfile() function always returns an error.
clock() The clock() function always returns -1. This is correct, according to the C
standard, because on AmigaOS it is not possible to obtain the time used by the
calling process.
14.7.7 libamiga.a
To write programs accessing AmigaOS (rather than standard C functions only), a replace-
ment for the original (copyrighted) amiga.lib is provided with vbcc. This replacement
(libamiga.a) automatically performs a necessary context switch to the 68k to execute
the system call. Furthermore, it is adapted to vbcc, does not cause collisions with some
functions (e.g. sprintf) provided by the original amiga.lib and is available in small data.
Specify -lamiga to link with libamiga.a.
Chapter 14: C Library 99
14.7.8 libauto.a
This library corresponds to the AmigaOS/68k version (See Section 14.5.9 [autolib], page 95).
14.8 WarpOS/PPC
This section describes specifics of the C library for WarpOS/PPC provided by the target
ppc-warpos. The relevant files are startup.o, vc.lib, m.lib, amiga.lib and auto.lib.
Note that extra.lib is no longer part of the vbcc distribution. It was replaced by
’PosixLib’, available on Aminet dev/c/vbcc_PosixLib.lha, which has a much more com-
prehensive support for POSIX and Unix functions.
14.8.1 Startup
The startup code startup.o sets up some global variables and initializes stdin, stdout and
stderr. The exit code closes all open files and frees all memory. If you link with a math
library the startup/exit code will be taken from there if necessary.
14.8.3 Stack
Stack-handling is similar to AmigaOS/68k (See Section 14.5.3 [amiga-stack], page 92).
14.8.4 Restrictions
The following list contains some restrictions of this version of the library:
tmpfile()
The tmpfile() function always returns an error.
clock() The clock() function always returns -1. This is correct, according to the C
standard, because on AmigaOS it is not possible to obtain the time used by the
calling process.
14.8.5 amiga.lib
To write programs accessing AmigaOS (rather than standard C functions only), a replace-
ment for the original (copyrighted) amiga.lib is provided with vbcc. This replacement
automatically performs a necessary context switch to the 68k to execute the system call.
100 vbcc manual
Furthermore, it is adapted to vbcc, does not cause collisions with some functions (e.g.
sprintf) provided by the original amiga.lib and is available in small data.
Specify -lamiga to link with amiga.lib.
14.8.6 auto.lib
This library corresponds to the AmigaOS/68k version (See Section 14.5.9 [autolib], page 95).
14.9 MorphOS/PPC
This section describes specifics of the C library for MorphOS/PPC provided by the target
ppc-morphos. The relevant files are startup.o, minstart.o, libvc.a, libvcs.a, libm.a,
libms.a libamiga.a, libamigas.a, libauto.a and libautos.a.
Note that libextra.a is no longer part of the vbcc distribution. It was replaced by
’PosixLib’, available on Aminet dev/c/vbcc_PosixLib.lha, which has a much more com-
prehensive support for POSIX and Unix functions.
14.9.1 Startup
The startup code startup.o sets up some global variables and initializes stdin, stdout and
stderr. The exit code closes all open files and frees all memory. If you link with a math
library the startup/exit code will be taken from there if necessary.
14.9.3 Stack
Stack-handling is similar to AmigaOS/68k (See Section 14.5.3 [amiga-stack], page 92).
14.9.5 Restrictions
The following list contains some restrictions of this version of the library:
tmpfile()
The tmpfile() function always returns an error.
Chapter 14: C Library 101
clock() The clock() function always returns -1. This is correct, according to the C
standard, because on MorphOS it is not possible to obtain the time used by
the calling process.
14.9.6 libamiga.a
To write programs using AmigaOS compatible functions, a replacement for the original
(copyrighted) amiga.lib is provided with vbcc. This replacement (libamiga.a) will invoke
the MorphOS 68k emulator to execute the system function. Furthermore, it is adapted to
vbcc and does not cause collisions with some functions (e.g. sprintf) and is available in
small data.
Specify -lamiga to link with libamiga.a.
14.9.7 libauto.a
This library corresponds to the AmigaOS/68k version (See Section 14.5.9 [autolib], page 95).
14.10 AmigaOS4/PPC
This section describes specifics of the C library for AmigaOS4/PPC provided by the target
ppc-amigaos. The relevant files are startup.o, minstart.o, libvc.a, libvcs.a, libm.a,
libms.a libamiga.a, libamigas.a, libauto.a and libautos.a.
Note that libextra.a is no longer part of the vbcc distribution. It was replaced by
’PosixLib’, available on Aminet dev/c/vbcc_PosixLib.lha, which has a much more com-
prehensive support for POSIX and Unix functions.
14.10.1 Startup
The startup code startup.o sets up some global variables and initializes stdin, stdout and
stderr. Then it runs all constructors of dynamically linked libraries, before entering the
main program. The exit code runs all destructors of dynamically linked libraries, closes all
open files and frees all memory. If you link with a math library the startup/exit code will
be taken from there if necessary.
14.10.3 Stack
There is no automatic stack extension for AmigaOS 4! This should be done automatically
by the operating system.
102 vbcc manual
14.10.6 Restrictions
The following list contains some restrictions of this version of the library:
tmpfile()
The tmpfile() function always returns an error.
clock() The clock() function always returns -1. This is correct, according to the C
standard, because on AmigaOS it is not possible to obtain the time used by the
calling process.
Small data in dynamically linked executables
There is a bug in elf.library V52.4 (and earlier), which doesn’t load .sdata
and .sbss as a contiguous block into memory, when the executable requires
dynamic linking. I decided against writing a workaround, as the bug should be
fixed in OS4.
14.10.7 libamiga.a
In contrast to other amigalibs the OS4 libamiga.a doesn’t contain any stubs for calling
system functions. AmigaOS 4 system calls are done through special macros in the SDK’s
interface header files.
The library only includes some remaining amigalib functions, not already integrated into
the OS, like CreateIO(), but its use is discouraged.
Specify -lamiga to link with libamiga.a.
14.10.8 libauto.a
Include auto-open and -close functions for the most common OS libraries and interfaces.
May also be used together with newlib (see below).
14.10.9 newlib
14.10.9.1 Introduction
newlib.library is a shared AmigaOS4 library, which is covered by several BSD like licenses,
and includes standard ANSI and POSIX functions as well as some functions common in
Unix, BSD and similar operating systems. It is part of the OS4 SDK.
Chapter 14: C Library 103
The config file newlib will be created on installation to use the paths for header files and
libraries pointing to the newlib from the SDK.
What are the main differences between vclib and newlib?
− vclib contains (almost) only standard ANSI-C and some ISO-C99 functions. If you want
to port Unix programs you will probably miss a lot of functions. Also newlib supports
things like mapping Unix directory paths to Amiga paths or expanding wildcards in
command lines automatically.
− Programs compiled for newlib will be shorter because the code for all functions is not
contained in the executable itself.
− Programs compiled for newlib will need the shared object libc.so present when
started.
− Programs compiled for newlib will probably need more memory because the entire
(rather large) libc.so will be loaded into memory. With vclib only the functions your
program uses will be in RAM. However if you have several programs using newlib at
the same time only one copy of libc.so should be loaded.
Things you should note:
− With newlib you do not need extra math-libraries.
− You must link with a vbcc-specific startup.o from the newlib lib/ directory as startup
code. The config-file newlib will usually take care of this.
− You must use the newlib-includes from the SDK rather than the ones which are for
vc.lib. The config-file newlib will usually take care of this.
− There may be vbcc-related bugs in the SDK-newlib. Patches are automatically installed
when using the Amiga Installer. When installing the target manually, you also have
to fix the SDK manually. For a list of known SDK bugs at this point of time, See
Section 14.10.9.2 [Known Newlib Bugs], page 103.
"#barrier";
int __asm_tolower(__reg("r3") int) =
"\t.extern\t__ctype_ptr\n"
- "\tlis\t11,(__ctype_ptr)@ha\n"
- "\taddi\t11,11,(__ctype_ptr)@l\n"
+ "\tlis\t11,__ctype_ptr@ha\n"
+ "\tlwz\t11,11,__ctype_ptr@l(11)\n"
"\tlbzx\t12,11,3\n"
"\tandi.\t12,12,1\n"
"\tbeq\t$+8\n"
Note: This should be fixed with the latest OS4 SDK, and the V0.9h installer will no
longer install a patch!
− Newlib’s libauto.a contains no working vbcc-style constructors or destructors for
auto-opening or -closing of libraries. You can work-around it, by copying vclib’s
libauto.a to newlib’s lib-directory. Rename it, if you don’t want to overwrite the
gcc-version of it.
− Some header files, like sys/stat.h, use the reserved vbcc attribute __mask as an
argument name. The config file should take care of that, by redefining it as ___mask.
14.10.9.3 Usage
To compile a program to use newlib for OS4 you must make sure the proper config-file
(newlib) is used, e.g.
vc +newlib hello.c
With a new SDK this will usually generate a dynamically linked executable, which requires
libc.so. To force a statically linked executable:
vc +newlib -static hello.c
14.11.1 Startup
The startup code startup.o sets up some global variables and initializes stdin, stdout and
stderr and returns the unneeded memory to the system. The exit code closes all open files
and frees all memory.
14.11.3 Stack
The default stack size is 64k. There is a MiNT tool called stack which can adjust the stack
size of an executable to any value, by looking for a symbol named __stksize (defined by
vclib’s startup code).
Additionally the required stack size can be specified by defining a variable __stack (of type
size_t) with external linkage, as in other vbcc targets.
14.11.5 Restrictions
The following list contains some restrictions of this version of the library:
tmpfile()
The tmpfile() function always returns an error.
clock() The clock() function always returns -1. This is correct, according to the C
standard, because neither under TOS nor under MiNT it is possible to obtain
the time used by the calling process.
14.12 VideoCore/Linux
This section describes specifics of the C library for VideoCore under Linux provided by the
target vidcore-linux.
The relevant files are vcload, startup.o, libvc.a, libm.a, libms.a.
The config file vc4-linux is part of the library.
106 vbcc manual
14.12.1 Startup
The startup code startup.o sets up stack and heap and provides a function __armcall()
to transfer control to the loader on the ARM side. The startup process calls constructors
to set up some global variables and initialize stdin, stdout and stderr if needed.
14.12.3 Stack
The library contains a default stack of 32KB. If another size is needed, you can add the
following to your project:
.align 4
.space <desired-size, suitably aligned>
___stackend:
.global ___stackend
14.12.4 Heap
Currently, a global variable of 16KB is used to get memory for malloc() etc. If another size
is needed, you can add the following to your project:
#define HEAPSIZE <desired size>
char __heap[HEAPSIZE],*__heapptr=__heap;
size_t __heapsize=HEAPSIZE;
Note that this mechanism will likely be changed in the future!
14.12.6 Loader
A loader is required to execute VideoCore code from the ARM side. For standalone Video-
Core code, the provided loader can be used. Usually, it will be necessary to adapt the loader
to communicate between ARM and VideoCore side during runtime.
of relocations followed by n 32bit words containing an offset. For each offset, the address
will be relocated to the image load address.
14.12.7 Restrictions
The following list contains some restrictions of this version of the library:
− no real floating point support yet
− lots, lots, lots...
14.13.1 Startup
The startup code startup.o sets up stack and heap. The startup process calls constructors
to set up some global variables and initialize stdin, stdout and stderr.
The ATARI Jaguar has no OS, so it is impossible to define how input, output and files can
be handled. There are a few set of function you have to define if you want to use stdio.
Alternatively you can use the libjag.a. This library initializes a console window with
stdout support and uses optionally a SkunkBoard to redirect stderr and file I/O.
14.13.3 Stack
The library contains a default stack of 32KB. If another size is needed, you can add a global
variable named stack to your code:
14.13.4 Heap
Currently the free RAM is used as global heapsize for malloc() etc.
It is necessary to place a symbol named BSS END at the end of the BSS segment. The
heap allocates the free RAM between BSS END and the bottom of the stack.
If less size is needed feel free to manipulate the value of BSS END.
All allocated heap objects can be used as internal JAGUAR objects, because they are qhrase
aligned.
Chapter 14: C Library 109
/**
* param handle: handle from jagopen
*
* No need to handle stdin, stdout and stderr here
*/
void jagclose(int handle)
/**
* param handle: handle from jagopen
* param p: points to the char buffer to fill.
* param l: buffer size of p
* returns: >=0 number of read bytes
<0 indicate an error
*
* Handle stdin, stdout and stderr here
*/
size_t jagread(int handle,char *p,size_t l)
/**
* param handle: handle from jagopen
* param p: points to the char buffer to write.
* param l: number of bytes of p
* returns: >=0 number of bytes written
<0 indicate an error
*
* Handle stdin, stdout and stderr here
*/
size_t jagwrite(int handle,const char *p, size_t l)
/**
* param handle: handle from jagopen
110 vbcc manual
#include <stdio.h>
int main()
{
printf("Hello, world\n");
}
Keep in mind: Your JAGUAR will get a red background color to indicate main() has exited.
The jaglib API documentation is available in a separate document. There is more demo
code available in the jaglib-demo (https://github.com/toarnold/jaglib-demo) gibhub
repository.
14.14 6502/C64
This is a port of vclib to the C64.
14.14.1.1 Startup
The default linker file creates program files that are loaded to address 0x801. A BASIC
line is included so that the program can be started using RUN from BASIC. The startup
code will turn off the BASIC ROM to allow usage of RAM until 0xD000 and most of the
zero page without need for any special handling. The BSS segment will be cleared during
startup.
With the default configuration, after exiting the C program, an infinite loop will be entered.
When using the +c64r config, the program will return to BASIC an can be started again.
However, this needs additional memory as the init values for the data section have to be
stored in RAM. Also, some register values and zero page contents have to be saved. The
overhead depends on the amount of initialized variables.
Chapter 14: C Library 111
14.14.1.4 Stack
By default, the user stack is mapped from 0xC800..0xD000. The size can be changed at
the top of vlink.cmd.
14.14.1.5 Heap
Code and data/BSS are mapped starting after the BASIC init line. The heap is placed in
the remaining space to stack start.
14.14.1.6 Banking
The following banking models are supported:
-reuflat This library supports a REU using a flat 16MB address space. The memory has
to be addressed through far-pointers. It is not possible to declare variables in
the REU nor to place code in the REU. The memory is addressed as 0x000000
to 0xFFFFFF. All accesses through far-pointers are addressing the REU. It is
not possible to address the C64 memory through a far-pointer.
Far-pointer arithmetic only works on the lower 16bits. It is not possible to cross
a bank boundary using far-pointers. Huge-pointers will support this, but are
not yet fully implemented. In the meantime it is possible to use long integers
and cast them to far-pointers.
Use -lreuflat to link with this library. Note that the library does not check
for the presence of a REU.
-reubank This configuration reserves a 16KB memory space within the C64 memory as
window for banking. As the bank number is stored as a single byte (with bank
255 denoting the unbanked memory), it is only possible to address up to about
4MB of memory in the REU.
Variables and code can be mapped into the REU using the __bank() attribute
or #pragma bank. When calling a banked function, the corresponding bank will
be copied from the REU into the C64 memory window.
Use the +c64reu configuration to use this mechanism. Currently the linker file
provides 8 banks resulting in a 128K REU image. More banks can be added
for larger expansions.
112 vbcc manual
The configuration will create a usually C64 prg file containing the unbanked
code and data as well as a REU image with extension .b0. It must be loaded
(e.g. with an emulator or the TurboChameleon) before the prg file can is
executed.
14.14.2 Runtime
Apart from standard C library functions, libvc.a also provides a few runtime support
functions needed by the compiler. Apart from the math and floating point functions men-
tioned in the documentation of the 6502 backend, it includes functions for saving/restoring
registers.
14.14.3 stdio
stdio supports stdout, stderr (both using the screen) and stdin (keyboard). Both are
unbuffered by default.
Furthermore, file IO with standard C functions is supported for 1541 and compatible disk
drives. Other devices have not been tested. Only sequential reading and writing of files is
supported. No seeking etc. There are hardcoded limits for the maximum number of open
files and the maximum length of filenames.
The remove() and rename() functions are supported using 1541
By default, device ID 8 is used. Another device ID can be specified as prefix to the filename:
/* try to open file "test" on the second drive */
FILE *f;
f=fopen("9:test","r");
...
printf/scanf functions which support floating point are contained in the math library
only.
The floating point routines are based on SANE, somewhat adapted to the ABI of vbcc
using wrapper functions. These functions should be fully C and IEEE compliant and pro-
vide precise results for 32 and 64bit floating point numbers (the library actually internally
calculates all operation using 80bits, but vbcc currently only uses up to 64 bits).
Currently, this library probably must be run from RAM.
Most parts of the C library functions for floating point are implemented. The list currently
includes:
• exp(), expf(), expl()
• exp2(), exp2f(), exp2l()
• exp1m(), exp1mf(), exp1ml()
• pow(), powf(), powl()
• log(), logf(), logl()
• log1p(), log1pf(), log1pl()
• log2(), log2f(), log2l()
• log10(), log10f(), log10l()
• sqrt(), sqrtf(), sqrtl()
• sin(), sinf(), sinl()
• cos(), cosf(), cosl()
• tan(), tanf(), tanl()
• atan(), atanf(), atanl()
14.15 6502/NES
This is a port of vclib to the NES console.
14.15.1.2 Stack
By default, the user stack starts from 0x0800 growing downwards.
14.15.1.3 Heap
By default, code and data/BSS are mapped starting after the system stack at 0x0200. The
heap is placed in the remaining space to stack start.
114 vbcc manual
14.15.2 Runtime
Apart from standard C library functions, libvc.a also provides a few runtime support
functions needed by the compiler. Apart from the math and floating point functions men-
tioned in the documentation of the 6502 backend, it includes functions for saving/restoring
registers.
14.15.3 stdio
At the moment, stdio only supports stdout, stderr (both using the screen) and stdin
(simple input via joypad).
printf/scanf functions which support floating point are contained in the math library
only.
For input, up/down changes the current character, left/right moves the cursor, the B button
deletes from the cursor position, and the A button confirms the input. You do not want to
use this in real code.
The library contains a default character set. To replace it, link an object that contains a
character set mapped to section chars and defines the global symbol ___stdchr.
To replace stdio, the function __read() and __write() have to be implemented.
14.15.4 Interrupts
The library contains a default NMI implementation that is used for stdio handling and the
clock()-function. It can be replaced by linking with an own implementation that starts at
the global symbol ___nmi. In this case the stdio and timing functions from vclib can not
be used.
___irq can be used to overwrite the other IRQ vector. The default implementation in the
library immediately returns.
14.16 6502/Atari
This is a port of vclib to Atari 8bit computers.
14.16.1.1 Startup
The default linker file creates program files that are loaded to address 0x600. The memory
area can be adapted by changing MEMSTART and MEMEND in vlink.cmd.
With the default configuration, after exiting the C program, it will wait for pressing the
return key before returning to DOS.
14.16.1.4 Stack
By default, the startup code maps the user stack from MEMTOP-STACKLEN..MEMTOP. The
size can be changed at the top of vlink.cmd.
14.16.1.5 Heap
Code and data/BSS are mapped starting at MEMSTART. The heap is placed in the remaining
space to stack start.
14.16.1.6 Banking
Banking support for this target has not yet been implemented.
14.16.2 Runtime
Apart from standard C library functions, libvc.a also provides a few runtime support
functions needed by the compiler. Apart from the math and floating point functions men-
tioned in the documentation of the 6502 backend, it includes functions for saving/restoring
registers.
14.16.3 stdio
At the moment, stdio only supports stdout, stderr (both using the screen) and stdin
(keyboard). Both are line-buffered by default.
printf/scanf functions which support floating point are contained in the math library
only.
116 vbcc manual
14.17.1.1 Startup
The default linker file creates program files that are loaded to address 0x1900 up to 0x7B00
with 256 bytes of software stack. The memory area can be adapted by changing OSHWM,
HIMEM and STACKSTART in vlink.cmd.
With the default configuration (+bbc), after exiting the C program, the code will enter an
endless loop. If the reentrant configs are used (+bbcr or +bbcbr), the program will return
to the command prompt. As this requires saving the zero page, a bit more memory is used.
14.17.1.4 Stack
By default, the startup code maps the user stack from STACKSTART..HIMEM. The size can
be changed at the top of vlink.cmd.
14.17.1.5 Heap
Code and data/BSS are mapped starting at OSHWM. The heap is placed in the remaining
space to stack start.
14.17.1.6 Banking
When using the +bbcb or bbcbr configurations, vbcc supports banked memory, including
automated bank-switching. Up to 16 sections of 16K size are supported. Each section starts
at 0x8000.
The corresponding linker files vlinkb.cmd and vlinkbr.cmd can be edited to choose the
banks that are required. Unused banks can be removed by commenting out (using old-style
C-comments) the corresponding entries in the SECTIONS part of the linker file. When using
bank 1-3 the section in the linker file could look like this:
...
118 vbcc manual
SECTIONS
{
text : {*(text)} >ram
.dtors : { *(.dtors) } > ram
.ctors : { *(.ctors) } > ram
rodata : {*(rodata)} >ram
data: {*(data)} >ram
init : {*(init)} >ram
zpage (NOLOAD) : {*(zpage) *(zp1) *(zp2)} >zero
bss (NOLOAD): {*(bss)} >ram
/*
b0 : {.=PAGEADDR; *(text0) *(rodata0) *(data0) *(bss0)
RESERVE(PAGEADDR+PAGESIZE-.);
} >b0 AT>dummy0
*/
...
During the linking process, apart from the normal output file, a 16K large image for each
bank and a loader script will be generated. E.g. when using banks 1-3 and using the output
file name test, the following files will be generated:
test The unbanked code/data.
test.inf Info file with start address.
testb1 Image for bank1.
testb2 Image for bank2.
testb2 Image for bank2.
Chapter 14: C Library 119
loadtest Loader
The contents of the loader loadtest will look like this:
*srload testb1 8000 1
*srload testb2 8000 2
*srload testb3 8000 3
*run test
The program can be started with *exec loadtest.
14.17.2 Runtime
Apart from standard C library functions, libvc.a also provides a few runtime support
functions needed by the compiler. Apart from the math and floating point functions men-
tioned in the documentation of the 6502 backend, it includes functions for saving/restoring
registers.
14.17.3 stdio
stdout, stderr (both using the screen) and stdin (keyboard) are supported. Furthermore
normal file operations are possible using the usual C functions. There are hardcoded limits
on the maximum number of simultaneously open files as well as the length of filenames.
Sequential reading and writing is supported, but no seeking. Furthermore, the remove()
call is supported.
When using stdio to emit VDU control sequences, the function __vdu_sequence() is avail-
able to ensure verbatim 1:1 transmission of all characters:
/* print diagonal line */
__vdu_sequence(1);
for(int i=0;i<20;i++)
printf("\x1f%c%cO",i,i);
__vdu_sequence(0);
printf/scanf functions which support floating point are contained in the math library
only.
14.18 6502/MEGA65
This is a port of vclib to the MEGA65. This port is intended for the C65 mode with a C65
or compatible ROM (although the ROM is not used after the program is started). The C64
configuration can be used to create programs for the C64 mode.
14.18.1.1 Startup
The default linker file creates program files that are loaded to address 0x2001. A BASIC
line is included so that the program can be started using RUN from BASIC. The startup code
will switch to VIC-IV mode, remove write protection of ROM banks, turn on full speed and
change to a suitable mapping. The BSS segment will be cleared during startup.
There are two sets of configurations that affect the configuration of upper memory. The
standard versions (+m65s, +m65sr, +m65sb) will keep the IO area mapped in at $D000.
This will limit the contiguous memory block for unbanked configurations to 0xCFFF. For
banked configurations (see below) it will make a 16K window from 0x8000..0xBFFF avail-
able for banking. The large configurations (+m65l, +m65lr, +m65lb) will move the upper
bound for unbanked programs to 0xFFFF. With banking, 32K window will be available
from 0x8000..0xFFFF. In both cases the total amount of memory available for banking is
the same in both configurations.
While the large configurations provide larger contiguous memory areas, accesses to the IO
area have to be made through extended 28bit instructions which are much larger and slower.
For programs doing many IO accesses, the standard configurations are recommended.
With the default configurations, after exiting the C program, an infinite loop will be entered.
When using the reentrant (+m65sr, +m65lr) configs, the program will return to BASIC an
can be started again. However, this needs additional memory as the init values for the data
section have to be stored in RAM. Also, some register values and zero page contents have
to be saved. The overhead depends on the amount of initialized variables.
Caution: The current configuration assumes that the Z register always contains 0. To work
correctly, the Z register has to be 0 when C code is executed. The startup code will set it
correctly and the compiler generated code will not touch it. However, when calling other
code you may have to take care to save/restore the Z register or to set the Z register to 0
again.
14.18.1.4 Stack
By default, the user stack is mapped from 0xB800..0xC000. For the banked version, it
is mapped from 0x7800..0x8000. The size can be changed at the top of vlink.cmd and
vlinkbank.cmd.
122 vbcc manual
14.18.1.5 Heap
Code and data/BSS are mapped starting after the BASIC init line. The heap is placed in
the remaining space depending on the configuration.
14.18.1.6 Banking
The following banking models are supported:
+m65sb 16K window at 0x8000 with IO area mapped in at all times.
+m65lb 32K window at 0x8000.
Automated bank switching is supported in both modes. The mapping of banks to real
memory in the standard configuration is like this:
Unbanked: 0x000000..0x007FFF
Bank0: 0x008000..0x00BFFF
Bank1: 0x00C000..0x00FFFF
Bank2: 0x010000..0x013FFF
Bank3: 0x014000..0x017FFF
...
On the large configuration, it looks like this:
Unbanked: 0x000000..0x007FFF
Bank0: 0x008000..0x00FFFF
Bank1: 0x010000..0x017FFF
Bank2: 0x018000..0x01FFFF
Bank3: 0x020000..0x027FFF
...
In both cases, the program start is moved to 0x1000. When using the banked configurations,
the code can not be simply loaded from BASIC. The linker will create on large image without
any BASIC lines. The file can be executed from SD-card by using a special loader that can
be loaded from BASIC off a disk or disk image. When specifying a name as command line
argument (see above), the loader will try to load this image from SD-card. If no argument
is given, the loader will look for a file of the same name. Therefore by renaming the loader
it can be made to automatically run a specific file.
If the loader is on the current disk/image and myimage on the SD:
LOAD "LOADER"
RUN:REM MYIMAGE
After renaming LOADER to MYIMAGE, it can be done like this:
RUN "MYIMAGE"
The colour RAM will be relocated to 0xFF80800 before loading to avoid being overwritten
through the window at 0x1F800.
14.18.2 Runtime
Apart from standard C library functions, libvc.a also provides a few runtime support
functions needed by the compiler. Apart from the math and floating point functions men-
tioned in the documentation of the 6502 backend, it includes functions for saving/restoring
registers.
Chapter 14: C Library 123
14.18.3 stdio
At the moment, stdio only supports stdout, stderr (both using the screen) and stdin
(keyboard). Both are unbuffered by default. Using those streams will directly access the
screen buffer and keyboard hardware. No ROM functions are needed once the program
runs.
Furthermore it is possible to read files on the SD-card using standard C functions after
opening them using fopen(). Hyppo services are used to read those files. There are several
limitations due to the restrictions of Hyppo:
• Files can only be read sequentially, no seeking etc.
• Files can not be written to.
• Only one file can be open at the same time.
printf/scanf functions which support floating point are contained in the math library
only.
14.18.4 Multiplication/Division
When generating code for the MEGA65, vbcc will make use of hardware multiplier/divider.
This can greatly improve performance of such operations. Please note the following issues:
• Some versions of the MEGA65 core contain a bug in the hardware divider which will
calculate wrong results in certain cases. As workaround you can specify option -div-
bug to use (much slower) 6502 software routines instead. Multiplication is not affected
by the bug and will still be using the hardware multiplier.
• The hardware multiplier registers are mapped in the IO area. When using the large
configurations (+m65l, +m65lr, +m65lb), they can only be accessed using extended
28bit instructions. The code generator and library functions will handle this, but there
is some overhead (still nowhere near using software multiplication). If your code is
speed critical and uses many multiplications we strongly recomment to use the standard
configurations (+m65s, +m65sr, +m65sb). Those will set the option -m65io that tells
vbcc to use faster direct IO accesses.
14.18.5 Interrupts
The provided configurations will disable interrupts on the MEGA65. All the library func-
tions are written to work with disabled interrupts and do not use any ROM routines. The
interrupt handlers in existing C65 ROMs do not work well with assembly language code and
deficiencies in the mapping hardware make it very hard to use the ROM in a non-BASIC
environment.
If an application wants to use interrupts, interrupt vectors have to be installed at
0xFFFA..0xFFFF. Take care that there are always valid vectors visible at this address
(especially in a banked configuration). Also take care that those always point to a valid
handler that is visible (i.e. do not use an ISR in banked memory).
The floating point routines are based on Steve Wozniaks routines from the 70s, somewhat
adapted to the ABI of vbcc. These functions are small and reasonably usable, but they do
not fully satisfy the requirements of C99.
Only a part of the C library functions for floating point is implemented. The list currently
includes:
• exp()
• pow()
• log()
• log10()
14.19 6502/X16
This is a port of vclib to the Commander X16.
14.19.1.1 Startup
The default linker file creates program files that are loaded to address 0x801. A BASIC
line is included so that the program can be started using RUN from BASIC. The startup
code will turn off the BASIC ROM to allow usage of RAM until 0x9F00 and most of the
zero page without need for any special handling. The BSS segment will be cleared during
startup.
With the default configuration, after exiting the C program, an infinite loop will be entered.
When using the +x16r config, the program will return to BASIC an can be started again.
However, this needs additional memory as the init values for the data section have to be
stored in RAM. Also, some register values and zero page contents have to be saved. The
overhead depends on the amount of initialized variables.
14.19.1.4 Stack
By default, the user stack is mapped from 0x9700..0x9F00. The size can be changed at
the top of vlink.cmd.
14.19.1.5 Heap
Code and data/BSS are mapped starting after the BASIC init line. The heap is placed in
the remaining space to stack start.
14.19.1.6 Banking
Banking support for this target is not yet implemented.
14.19.2 Runtime
Apart from standard C library functions, libvc.a also provides a few runtime support
functions needed by the compiler. Apart from the math and floating point functions men-
tioned in the documentation of the 6502 backend, it includes functions for saving/restoring
registers.
14.19.3 stdio
At the moment, stdio only supports stdout, stderr (both using the screen) and stdin
(keyboard). Both are unbuffered by default.
126 vbcc manual
printf/scanf functions which support floating point are contained in the math library
only.
14.20 6502/PET
This is a port of vclib to the CBM PET series of computers.
14.20.1.1 Startup
The default linker file creates program files that are loaded to address 0x401. A BASIC line
is included so that the program can be started using RUN from BASIC. RAM is available
until 0x7FFF and most of the zero page without need for any special handling. The BSS
segment will be cleared during startup.
With the default configuration, after exiting the C program, an infinite loop will be entered.
When using the +petr config, the program will return to BASIC an can be started again.
However, this needs additional memory as the init values for the data section have to be
stored in RAM. Also, some register values and zero page contents have to be saved. The
overhead depends on the amount of initialized variables.
14.20.1.4 Stack
By default, the user stack is mapped from 0x7F00..0x7FFF. The size can be changed at
the top of vlink.cmd.
14.20.1.5 Heap
Code and data/BSS are mapped starting after the BASIC init line. The heap is placed in
the remaining space to stack start.
14.20.1.6 Banking
Automated banking is currently not supported.
14.20.2 Runtime
Apart from standard C library functions, libvc.a also provides a few runtime support
functions needed by the compiler. Apart from the math and floating point functions men-
tioned in the documentation of the 6502 backend, it includes functions for saving/restoring
registers.
128 vbcc manual
14.20.3 stdio
At the moment, stdio only supports stdout, stderr (both using the screen) and stdin
(keyboard). Both are unbuffered by default.
printf/scanf functions which support floating point are contained in the math library
only.
15 List of Errors
0. "declaration expected" (Fatal, Error, ANSI-violation)
Something is pretty wrong with the source.
1. "only one input file allowed" (Fatal)
vbcc accepts only a single filename to compile. You can use a frontend to compile
multiple files or perhaps you mistyped an option.
2. "Flag <%s> specified more than once" ()
You specified a command line option that should be specified only once more than
once. Maybe you have this option in your config-file and used it in the command line,
too? The first occurrence will override the latter ones.
3. "Flag <%s> needs string" (Fatal)
This option hast to be specified with a string parameter, e.g. -flag=foobar
4. "Flag <%s> needs value" (Fatal)
This option hast to be specified with an integer parameter, e.g. -flag=1234
5. "Unknown Flag <%s>" (Fatal)
This option is not recognized by vbcc. Perhaps you mistyped it, used the wrong case
or specified an option of the frontend to vbcc?
6. "No input file" (Fatal)
You did not specify an input file. Your source file should not start with a ’-’ and if you
use a frontend make sure it has the proper suffix.
7. "Could not open <%s> for input" (Fatal)
A file could not be opened.
8. "need a struct or union to get a member" (Error, ANSI-violation)
The source contains something like a.b where a is not a structure or union.
9. "too many (%d) nested blocks" (Fatal, Error)
vbcc only allows a maximum number of nested blocks (compund-statements). You can
increase this number by changing the line #define MAXN <something> in vbc.h and
recompiling vbcc.
10. "left block 0" (Error, ANSI-violation)
This error should not occur.
11. "incomplete struct <%s>" (Error, ANSI-violation)
You tried to get a member of an incomplete structure/union. You defined struct x y;
somewhere without defining struct x{...}.
12. "out of memory" (Fatal, Error)
Guess what.
13. "redeclaration of struct <%s>" (Error, ANSI-violation)
You may not redeclare a struct/union in the same block.
14. "incomplete type (%s) in struct" (Error, ANSI-violation)
Every member in a struct/union declaration must be complete. Perhaps you only
wanted a pointer to that type and forgot the ’*’ ?
132 vbcc manual
89. "operands for || and && have to be arithmetic or pointer" (Error, ANSI-violation)
90. "bitwise operations need integer operands" (Error, ANSI-violation)
91. "assignment discards const" (Warning, ANSI-violation)
You assigned something like (const type *) to (type *).
92. "relational expression needs arithmetic or pointer type" (Error, ANSI-violation)
93. "both operands of comparison must be pointers" (Error, ANSI-violation)
You wrote an expression like a == b where one operand was a pointer while the other
was not. Perhaps a function is not declared correctly or you used NULL instead of 0?
94. "operand needs arithmetic type" (Error, ANSI-violation)
95. "pointer arithmetic with void * is not possible" (Error, ANSI-violation)
Adding/subtracting from a pointer to void is not possible.
96. "pointers can only be subtracted" (Error, ANSI-violation)
You cannot add, multiply etc. two pointers.
97. "invalid types for operation <%s>" (Error, ANSI-violation)
98. "invalid operand type" (Error, ANSI-violation)
99. "integer-pointer is not allowed" (Error, ANSI-violation)
You may not subtract a pointer from an integer. Adding an integer or subtracting it
from a pointer is ok.
100. "assignment discards volatile" (Warning, ANSI-violation)
You assigned something like (volatile type *) to (type *).
101. "<<, >> and % need integer operands" (Error, ANSI-violation)
102. "casting from void is not allowed" (Error, ANSI-violation)
Casting something of type void to anything makes no sense.
103. "integer too large to fit into pointer" (Error, ANSI-violation)
You tried to assign an integer to a pointer that is too small to hold the integer. Note
that assignment of pointers<->integers is never portable.
104. "only integers can be cast to pointers" (Error, ANSI-violation)
105. "invalid cast" (Error, ANSI-violation)
106. "pointer too large to fit into integer" (Error, ANSI-violation)
You tried to assign a pointer to an integer that is too small to hold the pointer. Note
that assignment of pointers<->integers is never portable.
107. "unary operator needs arithmetic type" (Error, ANSI-violation)
108. "negation type must be arithmetic or pointer" (Error, ANSI-violation)
109. "complement operator needs integer type" (Error, ANSI-violation)
110. "pointer assignment with different qualifiers" (Warning, ANSI-violation)
You tried to assign a pointer to a pointer that points to a type with different qualifiers
(e.g. signed<->unsigned).
111. "dereferenced object is no pointer" (Error, ANSI-violation)
112. "dereferenced object is incomplete" (Error, ANSI-violation)
You tried to dereference a pointer to an incomplete object. Either you had a pointer to
an array of unknown size or a pointer to a struct or union that was not (yet) defined.
136 vbcc manual
if(i=0)...
This could an error, if you wanted if(i==0). If you turned on this warning and want
it to shut up for a certain expression you can cast it to its type, e.g.
if((int)(i=0))...
Note that only assignments with ’=’ will be warned, not ’+=’ etc.
165. "comparison redundant because operand is unsigned" (Warning)
A comparison with an unsigned variable is redundant, because the result will always
be constant, e.g.
unsigned int i; if(i<0)...
This usually is a programming error and can be avoided in all cases.
166. "cast to narrow type may cause loss of precision" (Warning)
A variable is cast to a type smaller than its original type, so that some information
may get lost. However this warning will be displayed in lots of cases where no problem
can arise, e.g. (short)(a==b).
167. "pointer cast may cause alignment problems" (Warning)
A pointer is cast to a pointer to a type with stricter alignment requirements, i.e. the
new pointer might be invalid if you do not know what you are doing. Those casts
should be avoidable in all ’usual’ cases.
168. "no declaration of global variable <%s> before definition" (Warning)
It is usually good to declare all global variables (including functions) in header files.
169. "’extern’ inside function" (Warning)
Declaration of external variables in inner blocks is usually not a good idea.
170. "dead assignment to <%s> eliminated" (Warning)
A variable is assigned a value that is never used or gets overwritten before it is used.
If this occurs in real code then there is either an error or an unnecessary assignment.
This is detected only in optimizing compilation.
171. "var <%s> is used before defined" (Warning)
The variable is used before it was assigned a value and therefore is undefined. It cannot
be detected if the code where it is used can be reached, but if it is reached it will cause
undefined behaviour. So it is most probably an error either way (see 170).
However not all uninitialized usages can be found.
Also note that the compiler may choose convenient values for uninitialized variables.
Example:
int f(int a) { int x; if(a) x=0; return(x); }
Here the optimizer may choose that x==0 if it is uninitialized and then only generate
a return(0); It can also happen that you get different values if you read an uninitialized
variable twice although it was not assigned a value in between.
This is only detected in optimizing compilation.
172. "would need more than %ld optimizer passes for best results" (Warning)
The optimizer would probably be able to do some further optimizations if you increased
the number of allowed passes with the -optpasses=n option.
140 vbcc manual
16 Backend Interface
16.1 Introduction
This chapter is under construction!
This chapter describes some of the internals of vbcc and tries to explain what has to be
done to write a code generator for vbcc. However if someone wants to write one, I suggest
to contact me first, so that it can be integrated into the source tree.
You have to create a new directory for the new target named machines/<target-name>
and write the files machine.c, machine.h and machine.dt. The compiler for this target
will be called vbcc<target-name> and can be built doing a make TARGET=<target-name>
bin/vbcc<target-name>.
From now on integer means any of char, short, int, long, long long or their unsigned
couterparts. Arithmetic means integer or float or double or long double. Elementary
type means arithmetic or pointer.
Note that this documentation may mention explicit values when introducing symbolic con-
stants. This is due to copying and pasting from the source code. These values may not be
up to date and in some cases can be overridden. Therefore do never use the absolute values
but rather the symbolic representations.
Every available target has at least one subdirectory with its name in vbcc/machines and
contains at least the files machine.h, machine.c and machine.dt. Target-specific object-
files will also be stored in that directory.
The executables will be placed in vbcc/bin/. The main compiler will be called
vbcc<target>.
CC Here you have to insert a command that invokes an ANSI C compiler you want
to use to build vbcc. It must support -D, -I, -c and -o the same like e.g. vc or
gcc. Additional options should also be inserted here. E.g. if you are compiling
for the Amiga with vbcc you should add -DAMIGA.
LDFLAGS Here you have to add options which are necessary for linking. E.g. some
compilers need special libraries for floating-point.
NCC
NLDFLAGS These are similar to CC and LDFLAGS but they must always describe a native
compiler, i.e. Programs compiled with NCC/NLDFLAGS must be executable on
the host system. This is needed because during the build programs may have
to be executed on the host.
An example for the Amiga using vbcc would be:
CC = vc -DAMIGA -c99
LDFLAGS = -lmieee
NCC = $(CC)
NLDFLAGS = $(LDFLAGS)
An example for a typical Unix-installation would be:
CC = cc
LDFLAGS = -lm
NCC = $(CC)
NLDFLAGS = $(LDFLAGS)
The following settings are probably necessary for Open/Free/Any BSD i386 systems:
CC = gcc -D_ANSI_SOURCE
LDFLAGS = -lm
NCC = $(CC)
NLDFLAGS = $(LDFLAGS)
16.2.3 Building vc
Note to users of Open/Free/Any BSD i386 systems: You will probably have to use GNU
make instead of BSD make, i.e. in the following examples replace "make" with "gmake".
Type:
make bin/vc
Chapter 16: Backend Interface 149
16.2.6 Configuring
Consult the vbcc-documentation for information on how to create the necessary config-files.
Now create a second directory containing all the sources to vbcc and set CC/LDFLAGS to vc
using the config-file for vbccB and NCC/NLDFLAGS to the A->A compiler. Type:
make bin/vc
make TARGET=C bin/vscC # omit if there is no machines/C/schedule.c
make TARGET=C bin/vbccC
struct IC{
struct IC *prev;
struct IC *next;
int code;
int typf;
int typf2;
[...]
struct obj q1;
struct obj q2;
struct obj z;
[...]
struct ext_ic ext; /* optional */
};
The only members relevant to the code generator are prev, next, code, typf, typf2,
q1, q2, z and (optionally) ext_ic.
prev and next are pointers to the previous and next IC. The first IC has prev==0 and the
last one has next==0.
typf and typf2 are the type of the operands of this IC. In most ICs all operands have the
same type and therefore only typf is used. However, some ICs have operands of different
types (e.g. converting an operand to another type or adding an integer to a pointer). typf2
is used in these cases.
Macros are provided which yield the type of an operand. q1typ(), q2typ() and ztyp()
return the type of the first source operand, the second source operand and the destination,
respectively. They have to be passed a pointer to a valid IC as argument. The results are
Chapter 16: Backend Interface 151
undefined if the IC does not contain the specified operand (e.g. q2typ() for an IC with
only a single operand).
The standard types which are defined by default are:
#define CHAR
#define SHORT
#define INT
#define LONG
#define LLONG
#define FLOAT
#define DOUBLE
#define LDOUBLE
#define VOID
#define POINTER
#define ARRAY
#define STRUCT
#define UNION
#define ENUM /* not relevant for code generator */
#define FUNKT
and can be additionally or’ed by
#define UNSIGNED
#define CONST
#define VOLATILE
#define UNCOMPLETE
However, only UNSIGNED is of real importance for the code generator. typf&NQ yields the
type without any qualifiers, typf&NU yields the type without any qualifiers but UNSIGNED.
It is possible for backends to define additional types. See Section 16.9.8 [exttypes], page 185,
for documentation on how to extend the type system.
16.3.2 Operands
q1, q2 and z are the source1 (quelle1 in German), source2 and target (ziel) operands,
respectively. If a result has to be computed, it always will be stored in the object z and
the objects q1 and q2 usually may not be destroyed during this operation (unless they are
aliased with the destination).
The objects are described by this structure:
struct obj{
int flags;
int reg;
int dtyp;
struct Var *v;
struct AddressingMode *am;
union atyps{
zchar vchar;
zchar vuchar;
zshort vshort;
152 vbcc manual
zushort vushort;
zint vint;
zuint vuint;
zlong vlong;
zulong vulong;
zllong vllong;
zullong vullong;
zmax vmax;
zumax vumax;
zfloat vfloat;
zdouble vdouble;
zldouble vldouble;
} val;
};
• VAR|REG|DREFOBJ
• VAR|VARADR
Also some other bits which are not relevant to the code generator may be set.
Constants will usually be in q2 if possible. One of the sources always is not constant and
the target is always an lvalue. The types of the operands can be queried using the macros
q1typ(), q2typ() and ztyp(). In most cases (i.e. when not explicitly stated) the type is
an elementary type (i.e. arithmetic or pointer).
am can be used to store information on special addressing modes. This has to be han-
dled by the by the code generator. However am has to be 0 or has to point to a struct
AddressingMode that was allocated using malloc() when the code generator returns.
struct AddressingMode has to be defined in machine.h.
val stores either the value of the object if it is a constant or an offset if it is a variable.
code specifies the operation. Fur further details see Section 16.3.5 [operations], page 156.
16.3.3 Variables
A struct Var looks like:
struct Var{
int storage_class;
[...]
char *identifier;
[...]
zmax offset;
struct Typ *vtyp;
[...]
char *vattr;
unsigned long tattr; /* optional */
};
The relevant entries are:
identifier
The name of the variable. Usually only of interest for variables with external-
linkage.
storage_class
One of:
#define AUTO 1
#define REGISTER 2
#define STATIC 3
#define EXTERN 4
#define TYPEDEF 5 /* not relevant */
The backend should use the macros isauto(), isstatic() and isextern()
to check which category a variable falls into.
offset Contains an offset relative to the beginning of the variable’s storage. Used, for
example, when accessing members of structures.
154 vbcc manual
vtyp The type of the variable (see Section 16.3.4 [compositetypes], page 154).
vattr A string with attributes used in the declaration of the variable. See
Section 16.9.6 [targetattributes], page 184, for further details.
tattr Flags used when declaring the variable. See Section 16.9.6 [targetattributes],
page 184, for further details.
If the variable is not assigned to a register (i.e. bit REG is not set in the flags of the
corresponding struct obj) then the variable can be addressed in the following ways (with
examples of 68k-code):
isauto(storage_class) != 0
offset contains the offset inside the local-variables section. The code generator
must decide how it’s going to handle the activation record. If offset < 0 then
the variable is a function argument on the stack. In this case the offset in the
parameter-area is - (offset + maxalign).
The code generator may have to calculate the actual offset to a stack- or frame-
pointer from the value in offset.
offset + val.vlong(sp)
Note that storage_class == REGISTER is equivalent to AUTO - whether the
variable is actually assigned a register is specified by the bit REG in the flags
of the struct obj.
isextern(storage_class) != 0
The variable can be addressed through its name in identifier.
val.vlong + ’_’identifier
isstatic(storage_class) != 0
The variable can be addressed through a numbered label. The label number is
stored in offset.
val.vlong+’l’offset
};
flags is the simple type as it is generally used in the backend. The meaning of the other
members depends on flags. attr is an attribute that can be added to the type using the
sytax __attr("...") (which is parsed like a type-qualifier, e.g. const). If several attributes
are specified for a type, the strings will be concatenated, separated by semi-colons.
If the type is a pointer (ISPOINTER(flags) != 0), then next will point to the type the
pointer points to.
If the type is an array (ISARRAY(flags) != 0), then size contains the number of elements
and next points to a type structure representing the type of each array element.
If the type is a structure (ISSTRUCT(flags) != 0), a union (ISUNION(flags) != 0) or a
function (ISFUNC(flags) != 0), then exact is a pointer to a struct_declaration (which
is also used to represent unions and function prototypes) that looks like this:
struct struct_declaration {
int count;
int label;
int typ;
...
struct struct_list (*sl)[];
char *identifier;
};
count is the number of members, label can be used to store a label when generating
debug information. typ is either STRUCT, UNION or FUNKT to denote whether it applies to a
structure, union or function-prototype.
identifier is only available for struct- and union-tags.
sl points to an array of struct struct_lists which contain information on each mem-
ber/parameter:
struct struct_list {
char *identifier;
struct Typ *styp;
zmax align;
int bfoffset;
int bfsize;
int storage_class;
int reg;
};
identifier is the identifier of the member/parameter, if available. styp denotes the full
type, align the alignment in bytes (only for struct/union), bfoffset and bfsize the size
and offset of bitfield-members, storage_class the storage class of function parameters
(may be AUTO or REGISTER) and reg denotes the register a parameter is passed in.
Example: If struct Typ *t points to a structure-type, then the type of the second structure
member can be accessed through (*t->exact->sl)[1].styp.
A prototyped function will have a last argument of type VOID unless it is a function accepting
a variable number of arguments. If a function was declared without a prototype it will have
156 vbcc manual
no parameters, a function declared with prototype accepting no arguments will have one
parameter of type VOID.
Also, in the case of a function type, the next-member of a struct Typ points to the return
type of the function.
16.3.5 Operations
This section lists all the different operations allowed in the intermediate code passed to the
backend. It lists the symbolic name of the code value (the value should not be used), a
template of the operands and a description. The description sometimes contains internals
(e.g. which types are stored in typf and which in typf2), but they should not be used.
Access them using the macros provided (e.g. q1typ,q2typ,ztyp) whenever possible.
#define ASSIGN 2
Copy q1 to z. q1->z.
q2.val.vmax contains the size of the objects (this is necessary if it is an array
or a struct). It should be accessed using the opsize()-macro. typf does not
have to be an elementary type!
The only case where typf == ARRAY should be in automatic initializations.
It is also possible that (typf&NQ) == CHAR but the size is != 1. This is created
for an inline memcpy/strcpy where the type is not known.
#define OR 16
#define XOR 17
#define AND 18
Bitwise boolean operations. q1,q2->z.
All operands are integers.
#define LSHIFT 25
#define RSHIFT 26
Bit shifting. q1,q2->z.
’q2’ is the number of shifts. All operands are integers.
#define ADD 27
#define SUB 28
#define MULT 29
#define DIV 30
Standard arithmetic operations. q1,q2->z.
All operands are of arithmetic types (integers or floating point).
#define MOD 31
Modulo (%). q1,q2->z.
All operands are integers.
#define KOMPLEMENT 33
Bitwise complement. q1->z.
All operands are integers.
#define MINUS 38
Unary minus. q1->z.
Chapter 16: Backend Interface 157
#define SUBIFP 82
Subtract an Integer from a pointer. q1,q2->z.
q1 and z are always pointers (of type typf2) and q2 is an integer of type typf.
z has to be q1 decreased by q2 bytes.
#define SUBPFP 83
Subtract a pointer from a pointer. q1,q2->z.
q1 and q2 are pointers (of type typf2) and z is an integer of type typf. z has
to be q1 - q2 in bytes.
#define GETRETURN 93
Get the return value of the last function call. ->z.
If the return value is in a register, its number will be q1.reg. Otherwise q1.reg
will be 0. GETRETURN immediately follows a CALL IC (except possible FREEREGs).
#define SETRETURN 94
Set the return value of the current function. q1.
If the return value is passed in a register, the register number will be z.reg.
Otherwise z.reg will be 0. SETRETURN is immediately followed by a function
exit (i.e. it is the last IC or followed by an unconditional branch to a label
which is the last IC - always ignoring possible FREEREGs).
#define MOVEFROMREG 95
Move a register to memory. q1->z.
q1 is always a register and z an array of size regsize[q1.reg].
#define MOVETOREG 96
Load a register from memory. q1->z.
z is always a register and q1 an array of size regsize[z.reg].
#define NOP 97
Do nothing.
If the code generator can use several representations, these can be added on the same line
separated by spaces. E.g. the code generator for m68k does not care if the integers are
stored big-endian or little-endian on the host system because it only accesses them through
the provided arithmetic functions. It does, however, access floats and doubles through
byte-pointers and therefore requires them to be stored in big-endian-format.
16.5 machine.h
This section describes the contents of the file machine.h. Note that some optional
macros/declaration may be described someplace else in this manual.
#include "dt.h"
This should be the first statement in machine.h.
struct AddressingMode { ... };
If machine-specific addressing modes (see Section 16.8.2 [addressingmodes],
page 173) are used, an appropriate structure can be specified here. Otherwise,
just enter the following code:
struct AddressingMode {
int never_used;
};
#define MAXR <n>
Insert the number of available registers.
#define MAXGF <n>
Insert the number of command line flags that can be used to configure the
behaviour of the code generator. This must be at least one even if you do not
use any flags.
#define USEQ2ASZ <0/1>
If this is set to zero, vbcc will not generate ICs with the target operand being
the same as the 2nd source operand. This can sometimes simplify the code-
generator, but usually the code is better if the code-generator allows it.
162 vbcc manual
#define AVOID_FLOAT_TO_UNSIGNED 1
#define AVOID_UNSIGNED_TO_FLOAT 1
Insert these lines to tell the frontend not to generate CONVERT ICs that con-
vert between unsigned integers and floating point. In those cases, additional
intermediate code will be generated that implements the conversion using only
signed integers.
16.6 machine.c
This is the main part of the code generator. The first statement should be #include
"supp.h" which will include all necessary declarations.
The following variables and functions must be provided by machine.c.
16.6.5 Functions
The following functions have to be implemented by the code generator. There may be
optional additional functions described in other sections.
int init_cg(void);
This function is called after the commandline arguments are parsed. It can
set up certain internal data, etc. The arrays regarding the data types and
Chapter 16: Backend Interface 167
the register set can be set up at this point rather than with a static initializa-
tion, however the arrays regarding the commandline options have to be static
initialized. The results of the commandline options are available at this point.
If something goes wrong, 0 has to be returned, otherwise 1.
void cleanup_cg(FILE *f);
This function is called before the compiler exits. f is the output file which must
be checked against 0 before using.
int freturn(struct Typ *t);
This function has to return the number of the register return values of type
t are passed in. If the type is not passed in a register, 0 must be returned.
Usually the decision can be made only considering t->flags, ignoring the full
type (see Section 16.3.4 [compositetypes], page 154).
int regok(int r, int t, int mode);
Check whether the type t can be stored in register r and whether the usual
operations (for this type) can be generated. Return 0, if not.
If t is a pointer and mode==0 the register only has to be able to store the pointer
and do arithmetic, but if mode!=0 it has to be able to dereference the pointer.
mode==-1 is used with context-sensitive register-allocation (see Section 16.8.10
[targetralloc], page 179). If the backend does not support it, this case can be
handled equivalent to mode==0.
If t==0 return whether the register can be used to store condition codes. This
is only relevant if multiple_ccs is set to 1.
int dangerous_IC(struct IC *p);
Check if this IC can raise exceptions or is otherwise dangerous. Movement of
ICs which are dangerous is restricted to preserve the semantics of the program.
Typical dangerous ICs are divisions or pointer dereferencing. On certain targets
floating point or even signed integer arithmetic can raise exceptions, too.
int must_convert(int from,int to,int const_expr);
Check if code must be generated to convert from type from to type to. E.g.
on many machines certain types have identical representations (integers of the
same size or pointers and integers of the same size).
If const_expr != 0 return if a conversion was necessary in a constant expres-
sion.
For example, a machine may have identical pointers and integers, but different
sets of registers (one set supports integer operations and the other pointer
operations). Therefore, must_convert() would return 1 (we need a CONVERT
IC to move the value from one register set to the other).
This would imply that vbcc would not allow a cast from a pointer to an integer
or vice-versa in constant expressions (as it will not generate code for static
initializations). However, in this case, a static initialization would be ok as
the representation is identical and registers are not involved. Therefore, the
backend can return 1 if const_expr == 0 and 0 otherwise.
168 vbcc manual
isstatic(sc)
Tests whether the storage-class sc denotes a variable with static storage and
no external linkage.
isextern(sc)
Tests whether the storage-class sc denotes a variable with static storage and
external linkage.
isauto(sc)
Tests whether the storage-class sc denotes a variable with automatic storage-
duration.
t_min(t)
t_max(t) These macros yield the smallest and largest representable value of any target
integer type, e.g. t_min(INT) or t_max(UNSIGNED|LONG).
ISPOINTER(t)
ISINT(t)
ISFLOAT(t)
ISFUNC(t)
ISSTRUCT(t)
ISUNION(t)
ISARRAY(t)
ISSCALAR(t)
ISARITH(t)
These macros test whether the simple type t is a pointer type, an integral type,
a floating point type, a function, a structure type, a union type, an array type,
a scalar (integer, floating point or pointer) and an arithmetic type (integer or
floating point), respectively.
int label;
The number of the last label used so far. For a new label number, use ++label.
The function returns 0 if no modification took place and non-zero if the IC has
been modified.
eval_const() reads the member of the union corresponding to the type t and
converts it into all the global variables while insert_const() takes the global
variable according to t and puts it into the appropriate member of the union
atyps.
The global variable gval may be used as a temporary union atyps by the
backend.
172 vbcc manual
Sometimes, a simple backend is sufficient and the work required to produce high-quality
code is not worthwhile. However, this section lists a series of common backend optimizations
which are often done in case that good code-quality is desired. Note that neither are all of
these optimizations applicable (without modifications or at all) to all architectures nor is
this an exhaustive list. It is just a list of recommendations to consider. You have to make
sure that the optimization is safe and beneficial for the architecture you are targetting.
it. The machine independent part of vbcc will not use these modes, so your code generator
has to find a way to combine several statements to make use of these modes.
A possible implementation of a structure to handle the addressing mode described above
as well as a register-indirect mode could be:
#define IMM_IND 1
#define REG_IND 2
struct AddressingMode {
int flags; /* either IMM_IND or REG_IND */
int base; /* base register */
zmax offset; /* offset in case of IMM_IND */
int idx; /* index register in case of REG_IND */
}
When the code generator is done that pointer in every struct obj must either be zero or
point to a mymalloced struct AddressingMode which will be free’d by vbcc.
Following is an example of a function which traverses a list of ICs and inserts addressing
modes with constant offsets where possible.
/* search for possible addressing-modes */
static void find_addr_modes(struct IC *p)
{
int c,c2,r;
struct IC *p2;
struct AddressingMode *am;
for(;p;p=p->next){
c=p->code;
if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&
isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
/* we have found addi2p q1,#const->reg */
int base;zmax of;struct obj *o;
eval_const(&p->q2.val,p->typf);
/* handle sub instead of add */
if(c==SUBIFP)
of=zmsub(l2zm(0L),vmax);
else
of=vmax;
base=p->q1.reg;
else
base=r;
o=0;
/* Now search the following instructions. */
for(p2=p->next;p2;p2=p2->next){
c2=p2->code;
if(c2!=CALL&&(c2<LABEL||c2>BRA)&&c2!=ADDRESS){
/* See, if we find a valid use (dereference) of the
temporary register. */
if(!p->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&
p2->q1.reg==r){
if(o) break;
o=&p2->q1;
}
if(!p->q1.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&
p2->q2.reg==r){
if(o) break;
o=&p2->q2;
}
if(!p->q1.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&
p2->z.reg==r){
if(o) break;
o=&p2->z;
}
}
if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
int m;
if(c2==FREEREG)
m=p2->q1.reg;
else
m=p2->z.reg;
if(m==r){
/* The value of the temporary register is not used any more
176 vbcc manual
Care has to be taken to delete this information if either the condition codes may be modified
or the object they represent is modified. Also, this optimization is usually hard to do across
labels.
Some architectures provide versions of instructions which set condition codes as well as
versions which do not. This obviously enable more optimizations, but it is more difficult to
make use of this. One possibility is to search the list of ICs backwards starting from every
suitable TEST or COMPARE instruction. If an IC is found which computes the tested object,
the IC can be marked (extended ICs can be used for marking, see Section 16.8.13 [extic],
page 180).
Chapter 16: Backend Interface 177
number of cases that are used divided by the range of cases. If the density is high, vbcc
will use jump-tables only for sequences that have few unused cases inside. If the case tables
occupy multiple ranges, vbcc is able to split them up and create multiple jump-tables.
calc_case_table returns a pointer to a struct case_table with the following content:
num The number of cases.
typf The type of the case IDs.
next_ic The first IC after the list of ICs that can be replaced by the jump-table.
density The case density.
vals The values of the case IDs (array containing num entries).
labels The labels of the code corresponding to the case IDs (array containing num
entries).
min The lowest case ID.
max The highest case ID.
diff max-min.
If the backend decides to emit a jump-table, it has to generate code that will check that the
control expression lies between min and max. If not, the jump-table must not be executed.
Code for the computed jump must then be generated. The actual table can be emitted
using emit_jump_table(). Processing can then continue with next_ic.
{
int entries,i,r1,r2;
long x,y;
/* pointer to the lines in order of output */
char *asmline[EMIT_BUF_DEPTH];
i=emit_l;
/* compute number of entries in ring buffer */
if(emit_f==0)
entries=i-emit_f+1;
else
entries=EMIT_BUF_DEPTH;
/* the first line */
asmline[0]=emit_buffer[i];
if(entries>=2){
/* we have at least two line sin the buffer */
/* calculate the next line (modulo EMIT_BUF_DEPTH) */
i--;
if(i<0) i=EMIT_BUF_DEPTH-1;
asmline[1]=emit_buffer[i];
if(sscanf(asmline[0],"\tadd\tR%d,#%ld",&r1,&x)==2&&
sscanf(asmline[1],"\tadd\tR%d,#%ld",&r2,&y)==2&&
r1==r2){
sprintf(asmline[1],"\tadd\tR%d,#%ld\n",r1,x+y);
remove_asm();
return 1;
}
}
return 0;
}
Be very careful when doing such optimizations. Only perform optimizations which are really
legal. Especially assembly code often has side effects like setting of flags.
Depending on command line flags inline assembly code may or may not be passed through
this peephole optimizer. By default, it will be done, enabling optimizations between gener-
ated code and inline assembly.
may be set up and a stack frame will be created. It is generally worthwile to optimize this
entry/exit code. For example, if no registers need to be saved and no local variables are
used on the stack, it may not be necessary to create a stack frame.
The exact possibilities for optimization depend on the architecture and the ABI.
− Set INLINEMEMCOPY to reasonable values. Set it to a very high value if you implement
very good block copying.
16.9.2 -speed/-size
Often it is desired to generate code which runs as fast as possible but sometimes small code
is needed. The command line options -speed and -size are provided for the user to specify
his intention.
184 vbcc manual
These options already may change the intermediate code produced by the frontend, but
the backend should also respect these switches, if possible. The variables optspeed and
optsize can be queried to see if these options were specified.
If e.g. optspeed was specified, the backend should choose faster code-sequences, even if
code-size is increased significantly. Vice-versa, if optsize is specified, it should always
choose the shorter code if there is a trade-off between size and speed.
Typical cases for such tradeoffs are for example, block-copy (ASSIGN and PUSH) ICs. Often
it is possible to call a library function or generate a simple short loop for small code, but
an unrolled inlined loop for fast code.
16.9.4 stdarg.h
FIXME: To be written.
16.9.10.1 DWARF2
There is support for the DWARF2 debug standard which can be added to a backend rather
easily. The following additions are necessary:
1. Add the line
#include "dwarf2.c"
to machine.c.
2. Add the following lines to init_db():
dwarf2_setup(sizetab[POINTER],
".byte",
".2byte",
".4byte",
".4byte",
labprefix,
idprefix,
".section");
dwarf2_print_comp_unit_header(f);
The arguments to dwarf2_setup() have the following meanings:
1. The size of an address on the target.
2. An assembler directive to create one byte of initialized storage.
3. An assembler directive to create two bytes of initialized storage (without any
padding for alignment).
4. An assembler directive to create four bytes of initialized storage (without any
padding for alignment).
5. An assembler directive to create initialized storage representing a target address
(without any padding for alignment).
6. A prefix which is used for emitting numbered labels (or empty string).
7. A prefix which is used for emitting external identifiers (or empty string).
8. An assembler directive to switch to a new named section.
3. Add the line
dwarf2_cleanup(f);
to cleanup_db().
4. Write the function
static int dwarf2_regnumber(int r);
which returns the DWARF2 regnumber for a vbcc register number.
5. Write the function
static zmax dwarf2_fboffset(struct Var *v);
which returns the offset of variable v from the DWARF2 frame-pointer.
6. Write the function
static void dwarf2_print_frame_location(FILE *f,struct Var *v);
which prints a DWARF2 location of the frame pointer. It can use the function
void dwarf2_print_location(FILE *f,struct obj *o);
Chapter 16: Backend Interface 187
to output the location. For example, if the frame pointer is a simple register, it might
look like this:
static void dwarf2_print_frame_location(FILE *f,struct Var *v)
{
struct obj o;
o.flags=REG;
o.reg=frame_pointer_register;
o.val.vmax=l2zm(0L);
o.v=0;
dwarf2_print_location(f,&o);
}
7. Before emitting code for an IC p, execute the code
if(debug_info)
dwarf2_line_info(f,p);
8. After emitting code for a function v, a new numbered label has to be emitted after the
function code and the function
void dwarf2_function(FILE *f,struct Var *v,int endlabel);
must be called.
Note that the DWARF2 standard supports use of location lists which can be used to describe
a variable whose location changes during the program (e.g. in a register for some time, then
in memory and again in a register) as well as a moving frame pointer (very useful if no
separate frame pointer is used but all local variables are accessed through a moving stack
pointer). Unfortunately, none of the debuggers I have tried so far could handle these location
lists. Therefore, the current DWARF2 module does not output location lists, but future
version will probably offer them as an option.
Without location lists, accessing local variables will only work with a fixed frame pointer and
no register variables. Even with these restrictions, function parameters which are passed in
registers will not be correctly displayed during the function entry code.
The library function is responsible to take into account its own stack-frame.
16.9.13 Profiling
FIXME: To be written.