HP3000-L Archives

December 1997, Week 1

HP3000-L@RAVEN.UTC.EDU

Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Mark Klein <[log in to unmask]>
Reply To:
Mark Klein <[log in to unmask]>
Date:
Fri, 5 Dec 1997 12:37:50 PST
Content-Type:
text/plain
Parts/Attachments:
text/plain (234 lines)
>The programmer in question is a C / UNIX programmer new to the 3K, using
>the gnu c++ compiler. Me, I don't use intrinsics for I/O, so am almost
>useless (but please don't quote me on that). Can someone help us
>understand this behavior?

[snip]

It would be nice to see more of the code around the FOPEN, but I'm
pretty sure it is because you've not declared and initialized the rest
of the parameters. Please note that many intrinsics are declared IN THE
INTRINSICS FILE with default parameters such that if you don't supply
them all, the defaults will automatically be assigned. However, gcc
doesn't look at the intrinsics file, so you have to declare the
parameters and initialize them yourself. What can account for the
randomness of it succeeding and failing is the values left over in your
frame that happen to fall in the correct positions to be intpreted as
parameters to FOPEN.

There are other complications too when calling intrinsics in that some
parameters can be long pointers. I find that Lund's toolkit tool CSEQ
(written by Stan) is almost a requirement if you plan to use intrinsics
with gcc. I also have a file called longpointer.h that helps implement
long pointers with gcc.

I periodically publish the attached goo in support of long pointers, and
I guess this is as good an opportunity.

First, here is a (somewhat messy, but you'll get the idea) chunk of code
I wrote for the Java port. It shows an implementation that should work
with both HP/C and gcc:

#ifdef __GNUC__
extern void HPGETPROCPLABEL(    int    parms,
                                void * procname,
                                void * plabel,
                                void * status,
                                void * firstfile,
                                int    casesensitive,
   /* following added in 5.5 */ int    symbol_type,
                                void * data_size,
                                int    position,
                                int    search_path,
                                int    binding);
extern void HPFIRSTLIBRARY(     int    parms,
                                void * mpename,
                                void * status,
                                void * mpelength,
                                void * firstlib,
                                void * length,
                                void * syntax);
extern void HPMYPROGRAM(        int    parms,
                                void * mpename,
                                void * status,
                                void * mpelength,
                                void * progname,
                                void * length,
                                void * syntax);
#define T_STATUS struct { short subsys; short info; }
#define CALL_HPGETPROCPLABEL(procname, plabel, status, \
        firstfile, casesensitive, symbol_type, data_size, \
        position, search_path, binding) \
  HPGETPROCPLABEL(10, (procname), (plabel), (status),   \
                  (firstfile), (casesensitive), (symbol_type), \
                  (data_size), (position), (search_path), (binding));
#define CALL_HPFIRSTLIBRARY(mpefile, status, mpelength,\
                            firstlib, length, syntax)  \
  HPFIRSTLIBRARY(6, (mpefile), (status), (mpelength),  \
                (firstlib), (length), (syntax))
#define CALL_HPMYPROGRAM(mpefile, status, mpelength,   \
                         progname, length, syntax)     \
  HPMYPROGRAM(6, (mpefile), (status), (mpelength),     \
                (progname), (length), (syntax))
#else
#pragma intrinsic HPGETPROCPLABEL
#pragma intrinsic HPFIRSTLIBRARY
#pragma intrinsic HPMYPROGRAM
#define T_STATUS t_mpe_status
#define CALL_HPGETPROCPLABEL(procname, plabel, status, \
          firstfile, casesensitive, symbol_type, data_size, \
          position, search_path, binding) \
  HPGETPROCPLABEL((procname), (plabel), (status),   \
                  (firstfile), (casesensitive), (symbol_type), \
                  (data_size), (position), (search_path), (binding));
#define CALL_HPFIRSTLIBRARY(mpefile, status, mpelength, \
                            firstlib, length, syntax)   \
  HPFIRSTLIBRARY((mpefile), (status), (mpelength),
                 (firstlib), (length), (syntax))
#define CALL_HPMYPROGRAM(mpefile, status, mpelength,    \
                            progname, length, syntax)   \
  HPMYPROGRAM((mpefile), (status), (mpelength),         \
                 (progname), (length), (syntax))
#endif

Note that the intrinsics are not directly called within the code, but
through the CALL_ macros. For the gcc version, I've declared and used
the "hidden" parameters that these intrinsics require.

None of the above examples use long pointers. However, the PRINT
intrinsic does, and here is a simple example of how to do that in gcc:

#include "longpointer.h"

main()
  {
  char *buf = "this is a test!";
  char  buf1[80];
  int   ccode;

  extern int    CCODE();
  extern int    errno;

  extern void   PRINT(LONGPOINTER lp,
                      short       length,
                      short       control);

  LONGPOINTER lp_buf = longaddr(buf);
  PRINT(lp_buf,-strlen(buf),0);
  ccode = CCODE();
  sprintf(buf1, "ccode from PRINT call: %d\n",ccode);
  PRINT(longaddr(buf1),-strlen(buf1),0);
  if (errno != 0)
    {
    sprintf(buf1, "errno: %d\n", errno);
    PRINT(longaddr(buf1),-strlen(buf1),0);
    }
  };

Finally, here is the goo called "longpointer.h". I hope this little
gcc tutorial was informative.

/tmp(227): cat longpointer.h

typedef struct {
  int           spaceid;
  unsigned int  offset;
  } LONGPOINTER;


int getspaceid(void *source)
  {
  /*
   * Given the short pointer, determine it's space ID.
   */

  asm("comiclr,= 0,%r26,%r28");
  asm("ldsid (%r0,%r26),%r28");
  };

LONGPOINTER longaddr(void *source)      // %r26 == offset
  {
  /*
   * Return the long pointer for the address in sr5 space.
   */

  asm("or %r26,%r0,%r29");
  asm("comiclr,= 0,%r26,%r28");
  asm("ldsid (%r0,%r26),%r28");
  };

void longmove(int len,                  // %r26 == byte length
              LONGPOINTER source,       // %r23 == source space, %r24 == off
              LONGPOINTER target)       // sp-#56 == target space, sp-#52== off
  {
  /*
   * Move data between two buffers in long pointer space.
   */

  /*
   * This goo is to remove data from arg0-arg3 and place it in the frame
   * since these registers are needed for the millicode call.
   */
  int bytelen = len;
  int srcspace = source.spaceid;
  int srcoff   = source.offset;
  int trgspace = target.spaceid;
  int trgoff   = target.offset;

  asm(".import $$lr_unk_unk_long,MILLICODE");
  /*
   * The colons separate output from input parameters. In this case,
   * there are no output references from the instructions. The "m"
   * constraint indicates that the following token is a memory reference.
   * The general format is:
   *   asm("<instruction template>" : <output> : <input>);
   *     where <output> and <input> are:
   *       "<constraint>" (<token>)
   *     <instruction template> is the PA-RISC instruction in template fmt.
   * Refer to the gcc documentation or http://www.dis.com/gnu/gcc_toc.html
   */
  asm("ldw %0,%%r1"     :: "m" (srcspace));     // load source space to %r1
  asm("mtsp %r1,%sr1");                         // copy source space to %sr1
  asm("ldw %0,%%r26"    :: "m" (srcoff));       // load source offset to %r26
  asm("ldw %0,%%r24"    :: "m" (len));          // load length to %r24
  asm("ldw %0,%%r25"    :: "m" (trgoff));       // load target offset to %r25
  asm("ldw %0,%%r1"     :: "m" (trgspace));     // load target space to %r1
  asm("bl $$lr_unk_unk_long,%r31");             // start branch to millicode
  asm("mtsp %r1,%sr2");                         // copy target space to %sr2
  };

int longpeek(LONGPOINTER source)        // %r25 == spaceid, %r26 == offset
  {
  /*
   * Fetch the int in long pointer space.
   */
  asm("mtsp %r25,%sr1");
  asm("ldw 0(%sr1,%r26),%r28");
  };

void longpoke(LONGPOINTER target,       // %r25 == spaceid, %r26 == offset
          unsigned int val)             // %r24 == value
  {
  /*
   * Store the val into long pointer space.
   */
  asm("mtsp %r25,%sr1");
  asm("stw  %r24, 0(%sr1,%r26)");
  };

void move_fast(int len,                 // %r26 == byte length
               void *src,               // %r25 == source addr
               void *trg)               // %r24 == target addr
  {
  /*
   * Move using short pointers.
   */
  asm(".import $$lr_unk_unk,MILLICODE");
  asm("or %r26,%r0,%r1");               // Copy length to %r1 (temp)
  asm("or %r25,%r0,%r26");              // Move source addr into position
  asm("or %r24,%r0,%r25");              // Move target addr into position
  asm("bl $$lr_unk_unk,%r31");          // Start branch to millicode
  asm("or %r1,%r0,%r24");               // Move length into position
  };
/tmp(228):

ATOM RSS1 RSS2