Many C compilers support an intrinsic function asm(...) to provide a general means of inserting native machine instructions directly into a program through inline assembly. The syntax of the asm function uses a very general text-substitution scheme into which the requirements for many assembly languages can be accommodated: asm volatile ( "pattern for machine instruction(s)" : list of outputs : list of inputs : list of indirectly modified items ); where volatile is optional but may inhibit some compilers from deleting, moving appreciably, or combining the machine instructions; where instructions can be separated with \n\t; and where __asm__ is an alternate keyword for ISO C compatibility. Output or input parameters to be assigned by the compiler are designated in order of appearance in the pattern, left to right, as %0, %1, etc. One item that may be indirectly modified through asm code is "memory" and another is "cc" (condition codes for an architecture having them). Figure F-2 shows the asm function inserted into the SQUARES program (Section 1.7.1), with a view to gain some measure of cycles consumed for the central calculations. Like the HP-UX compilers, however, gcc moves the asm function when it is allowed to optimize a program. From a different point of view, with anything except a performance monitor, it is an advantage that the compiler can take inline assembly code into the purview of optimization activity. Figure F-2 SQUARES program containing the asm function#include <stdio.h> int main() { unsigned long long t1, t2; long long sq1, sq2, sq3; long long temp, diff1, diff2; asm volatile ("mov %0=ar.itc;;" : "=r"(t1) :: "memory"); diff1 = 1; diff2 = 2; temp = 1; sq1 = temp; diff1 = diff2 + diff1; temp = diff1 + temp; sq2 = temp; diff1 = diff2 + diff1; temp = diff1 + temp; sq3 = temp; asm volatile ("mov %0=ar.itc;;" : "=r"(t2) :: "memory"); printf("%lld\t%lld\t%lld\n", sq1, sq2, sq3); printf("%lld\t%lld\t%lld\n", t1, t2, t2-t1); return 0; } |