Software examples
Benchmark example
The difficulty faced here appears to be a very simple one, yet actually
poses an interesting challenge. The goal was to provide a simple method of
testing system performance of different VMEbus processor boards to enable a
suitable board to be selected. The problem was not how to measure the
performance — there were plenty of benchmark routines available — but how to
use the same compiler to create code that would run on several different
sys-tems with the minimum of modification. The idea was to generate some code
which could then be tested on several different VMEbus target systems to obtain
some relative performance figures. The reason for using the compiler was that
typical C routines could be used to generate the test code.
The first decision made was to restrict the C compiler to non-I/O
functions so that a replacement I/O library was not needed for each board. This
still meant that arithmetic operations and so on could be performed but that
the ubiquitous printf
statements and disk access would not be supported. This decision was more to do
with time constraints than anything else. Again for time reasons, it was
decided to use the standard UNIX-based M680x0 cc compiler running on a UNIX
system. The idea was not to test the compiler but to provide a vehicle for
testing relative performance. Again, for this reason, no optimisation was done.
A simple C program was written to provide a test vehicle as shown. The exit() command was deliberately inserted to force the compiler to explicitly
use this function. UNIX systems nor-mally do not need this call and will insert
the code automatically. This can cause difficulties when trying to examine the
code to see how the compiler produces the code and what is needed to be
modified.
main()
{
int
a,b,c;
a=2;
b=4;
c=b-a; b=a-c; exit();
}
The example C program
The next stage was to look at the assembler output from the compiler.
The output is different from the more normal M68000 assembler printout for two
reasons. UNIX-based assemblers use different mnemonics compared to the standard
M68000 ones and, secondly, the funny symbols are there to prompt the linker to
fill in the addresses at a later stage.
The appropriate assembler source for each line is shown under the line
numbers. The code for line 4 of the C source appears in the section headed ln
4 and so on. Examining the code shows that some
space is created on the stack first using the link.l instruction. Lines 4 and 5 load the values 2 and 4 into the variable
space on the stack. The next few instructions perform the subtrac-tion before
the jump to the exit subroutine.
file “math.c”
data 1
text
def main; val main; scl 2; type 044; endef
global main
main:
ln 1
def ~bf; val ~; scl 101; line 2; endef
link.l %fp,&F%1
#movm.l &M%1,(4,%sp)
#fmovm &FPM%1,(FPO%1,%sp)
def a; val -4+S%1; scl 1; type 04;
endef
def b; val -8+S%1; scl 1; type 04;
endef
def c; val -12+S%1; scl 1; type 04;
endef
ln 4
mov.l &2,((S%1-4).w,%fp)
ln 5
mov.l &4,((S%1-8).w,%fp)
ln 6
mov.l ((S%1-8).w,%fp),%d1
sub.l ((S%1-4).w,%fp),%d1
mov.l %d1,((S%1-12).w,%fp)
ln 7
mov.l ((S%1-4).w,%fp),%d1
sub.l ((S%1-12).w,%fp),%d1
mov.l %d1,((S%1-8).w,%fp)
ln 8
jsr exit
L%12:
def ~ef; val ~; scl 101; line 9; endef
ln 9
#fmovm (FPO%1,%sp),&FPM%1
#movm.l (4,%sp),&M%1
unlk %fp
rts
def main; val ~; scl -1; endef
set S%1,0
set T%1,0
set F%1,-16
set FPO%1,4
set FPM%1,0x0000
set M%1,0x0000
data 1
The resulting assembler source code
This means that provided the main entry requirements are to set-up the
stack pointer to a valid memory area, the code located at a valid memory
address and the exit routine replaced with one more suitable for the target,
the code should execute correctly. The first point can be solved during the
code downloading. The other two require the use of the linker and replacement
run-time routine for exit. All the target boards have an onboard debugger which
provides a set of I/O functions including a call to restart the debugger. This
would be an ideal way of terminating the program as it would give a definite
visual signal of the termination of the software. So what was required was a
routine that executed this debugger call. The routine for a Flight MC68020
evaluation board (EVM) is shown. This method is generic for M68000-based VMEbus
boards. The other routines were very similar and basically used a different
trap call number, e.g. TRAP #14 and TRAP #15 as opposed to TRAP #11. The global
statement defines the label exit as an external reference so that the linker
can recognise it. Note also the slightly different syntax used by the UNIX
assembler. The byte storage command inserts zeros in the following long word to
indicate that this is a call to restart the debugger.
exit:
global exit
trap &11
byte 0,0,0,0
The exit() routine for the MC68020 EVM
This routine was then assembled into an object file and linked with the
C source module using the linker. By including the new exit module on the
command line with the C source module, it was used instead of the standard UNIX
version. If this version was executed on the UNIX machine, it caused a core
dump because a TRAP #11 system call is not normal.
SECTIONS
{
GROUP
0x400600:
{
.text
:{}
.data
:{}
.bss
:{}
}
}
The MC68020 EVM linker command file
The next issue was to relocate the code into the correct memory
location. With a UNIX system, there are three sections that are used to store
code and data, called .text, .data and .bss. Normally these are located
serially starting at the address $00000000. UNIX with its memory management
system will trans-late this address to a different physical address so that the
code can execute correctly, instead of corrupting the M68000 vector table which
is physically located at this address. With the target boards, this was not
possible and the software had to be linked to a valid absolute address.
This was done by writing a small command file with SECTIONS and GROUP
commands to instruct the linker to locate the software at a particular absolute
address. The files for the MC68020 EVM and for the VMEbus board are shown. This
file is included with the other modules on the command line.
SECTIONS
{
GROUP
0x10000:
{
.text
:{}
.data
:{}
.bss
:{}
}
}
The VMEbus board linker command file
To download the files, the resulting executable files were converted to
S-records and downloaded via a serial port to the respective target boards.
Using the debugger, the stack pointer was correctly set to a valid area and the
program counter set to the program starting address. This was obtained from the
symbol table generated during the linking process. The program was then
executed and on completion, returned neatly to the debugger prompt, thus
allowing time measurements to be made. With the transfer technique established,
all that was left was to replace the simple C program with more meaningful
code.
To move this code to different M68000-based VMEbus processors is very
simple and only the exit() routine
with its TRAP instruction
needs to be rewritten. To move it to other processors would require a change of compiler and a different version of
the exit() routine
to be written. By adding some additional code to pass and return parameters,
the same basic technique can be extended to access the onboard debugger I/O
routines to provide support for printf() statements and so on. Typically, replacement putchar() and getchar() routines
are sufficient for terminal I/O.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.