compat.html
8.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>/tmp/n46software.html</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
</head>
<body>
<h2>N64 Software Notes</h2>
May 2002<br>
<br>
The N64 source code is in the bb tree under the directory sw/n64os20j. This
subdirectory is essentially the contents of the PR (project reality) tree.
The source code is a merge of parts of two separate trees. The
n64os20j tree from Nintendo, used for continuing engineering to the n64 software
development kit after the hardware was completed and some of the hardware
components (rcp chip verilog source, test programs) from the SGI PR
tree that Nintendo had dropped from their software tree.<br>
<br>
The idea behind this N64 tree (n64os20j) is to have a working copy
of the verification and development environment for the N64 console. In
the short term, there shouldn't be any BBplayer specific changes to this
part of the tree -- more likely we will create a new subtree for BBplayer
development and copy the desirable portions from the n64os20j tree.<br>
<h3>Build Environment</h3>
The original development environment for the N64 was mips-based SGI workstations.
Since a mips processor running in big-endian mode was used in the N64
console, the development environment was relatively straightforward. For
example, the same compiler could be used for generating executable code to
run on the SGI machines and the N64 console.<br>
<br>
Much of the development environment has been ported to run on a linux-x86
cross development system. There are several significant differences
in this environment: the host system is little-endian x86, and the
host operating system is gnu/linux. Most of the SGI build style was
maintained by porting the makefiles to use GNU make, rather than SGI's smake.
Extra tools and files to support x86-linux development are in the
tree under sw/devroot/linux. To create a useable development environment
you need an updated copy of the source tree including sw/devroot and sw/n64os20j
and you need to set the environment variable $ROOT to point at a subdirectory
where headers, libraries, binaries, etc can be installed as part of the development
process. Note that $ROOT has little to do with the location of your
source tree (in SGI-speak, your source tree is pointed to by $WORKAREA, and
$ROOT points at the place where the result of building your source tree should
go).<br>
<br>
Before you can build the n64os20j source tree you need to install the devroot
tools. To do this you need to install some parts such as the mips-linux
cross compiler as root (it gets installed in /usr/mips-linux) and install
the rest as yourself:<br>
<br>
% cd sw/devroot/linux<br>
% su<br>
# make install_root<br>
^D<br>
% make install<br>
<br>
Note that the devroot is still evolving, so it is a good idea to frequently
update the devroot source and reinstall<br>
<br>
Once the devroot is built and installed, you can build the n64 tree from
the toplevel makefile:<br>
<br>
% cd sw/n64os20j<br>
% make headers<br>
% make exports<br>
% make<br>
<br>
make headers builds any generated header files and installs them in $ROOT/usr/include
(mostly in $ROOT/usr/include/PR). make exports builds tools that are
need by other parts of the build and installs them in $ROOT/usr/sbin and
$ROOT/usr/lib. make exports typically builds the entire 'product' part
of the source code, this includes all of the components of the n64 sdk (libraries,
rsp code, etc). the remaining make builds a few additional parts of
the tree.<br>
<h3>Porting/Cross Development Issues</h3>
Issues and strategies for dealing with porting the build environment are
documented here in the hopes of handling things in a consistent way. In
particular, the goal is to keep the tree in a state where the source code
can still be built on an SGI system if necessary. This mostly amounts
to ifdef'ing C source code changes using<br>
#ifdef __sgi__<br>
< original code><br>
#else<br>
< new x86 code><br>
#endif<br>
<br>
and creating separate makefiles.<br>
<br>
1) Makefile portability<br>
<br>
Some of the makefile syntax is not quite the same between SGI smake and GNU
make. In particular, the syntax for conditionals (#ifdef vs. ifdef,
if vs. ifeq) , and some of the special variables, syntax for built-in functions
etc. Rather than try to make changes to the existing Makefiles, we
take advantage of the fact that GNu make looks for a makefile with the name
GNUmakefile first before looking for Makefile. So if porting changes
are required, we make a copy of the existing Makefile as GNUmakefile and
make the changes to GNUmakefile.<br>
<br>
There are several makefile porting issues beyond syntax changes. Again,
many of the existing Makefiles assume that the same compiler and options
can be used to compile code targeted to run on the host system as targetted
to run on the N64 console. The SGI build tools include some makefile
variables to try to help with the problem, but they were not used in very
many places. Typically to compile a program intended for the host system,
the variable $(HOST_CC) is used to invoke the compiler, rather than $(CC).
Unfortunately, this mechanism is a little simplisitic since it doesn't
also provide definitions for $(HOST_CFLAGS), etc. I have found it simpler
to change GNUmakefiles that involve only code targetted for the host system,
to add a few lines such as<br>
CC=$(HOST_CC)<br>
GCINCS=-D_LANUAGE_C -I$(ROOT)/host_include<br>
GLDOPTS=<br>
to use the correct compilation environment with the smallest number of changes.<br>
<br>
Note that this demonstrates another problematic issue with the makefiles.
Some header files are used in code for both the host system and the
N64. Using -I($ROOT)/usr/include for host code often inadvertently
pulls in unwanted/conflicting headers. To minimize the problem, we
create $(ROOT)/host_include that also has a copy of the PR headers $ROOT/host_include/PR
to be used for host code. Similarly, there is a $(ROOT)/host_lib
that contains libraries specific for the host (this one is a little blurrier
since some Makefiles still put host libraries in $ROOT/usr/lib and it hasn't
been necessary to fix them since it works ok).<br>
<br>
2) C/Assembly code portability<br>
<br>
As mentioned above, to retain compatibility with the SGI system, it is preferred
to use #ifdef __sgi__ to keep both the old and new code. <br>
Many of the portability issues have to do with header files that existing
on the SGI system, but not the linux system. e.g., bstring.h. These
can be handled using #ifdefs. Some other differences include some library
differences such as as mmap(), SGI threads (sproc versus pthreads), etc.
These need to be handled on a case by case basis.<br>
<br>
3) Assembly code portability<br>
<br>
The tool chain we are using, allows the C-preprocess to be used with assembly
files to be compatible with the SGI assembler. However, it is a little
pickier. In particular, it doesn't like unmatched ' characters, even
in comments. I fix these by doubling them up, e.g.,<br>
<br>
ori r2,3 # don''t
you hate portability problems<br>
<br>
This issue is also true with the rsp assembler<br>
<br>
There are some directives that have slightly different forms, and can be
handled using #ifdef __sgi__<br>
.repeat <x>,<y> becomes .rept <x>, <y><br>
<br>
4) Endianness Issues<br>
<br>
The x86 uses little-endian byte order whereas the N64 console and SGI host
system are big-endian. Since the N64 target is big-endian, it makes
sense to maintain all external data representations in big-endian format.
This means that when necessary, programs running on x86-linux need
to convert to little endian (native endianness) when reading files, and convert
to big endian when writing them. To maximize portability, I have simply
been using the BSD networking functions (htons, ntohs, htonl, and ntohl).<br>
<br>
<br>
</body>
</html>