HP3000-L Archives

June 1999, 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:
Date:
Wed, 2 Jun 1999 09:28:41 -0700
Content-Type:
text/plain
Parts/Attachments:
text/plain (280 lines)
>I'm running into some difficulty reworking c89  #pragma intrinsics into
>reasonable prototypes that actually work on gcc/iX.  The resultant code
>does not seem to have the correct prologue and/or epilogue and the calls
>are failing.

There are usually hidden parameters that need to be addressed and there
are some long pointer issues to deal with. The easiest way to do this
is invest in the Lund Developer's Toolbox (written by Allegro). (I don't
get no steenking commissions ... so a plug alert isn't warranted. :-))
You're interested most in the CSEQ tool. It will produce calling sequences
for the intrinsics. And, if you SET GCC, it will produce gcc compatible
declarations. You may still need to dummy up some declarations if you
don't have them (typically typedefs) and you'll need my longpointer.h
goo (a version included below).

The following is an example implementation of a call to HPGETPROCPLABEL:

#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);
#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));
#else
#pragma intrinsic HPGETPROCPLABEL
#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));
#endif

and in the code:

     ...
     CALL_HPGETPROCPLABEL(&buf,value,&status,lib,1,0,&dummy,0,0,0);
     if (status.info != 0) {...}

This follows my coding style and allows me to use the same body of code
for both c89 and gcc. Note that while the intrinsic is in essence option
variable, I supply all of the parameters, specifying the default values
for parameters I don't care about. CSEQ will tell you what those defaults
should be.

Here's an example using longpointers. This both moves data around using
long pointers, and calls an intrinsic expecting a longpointer as one of
the params:

#include "longpointer.h"

extern void PRINT(
        longpointer message,
        int         len,
        int         cctl);

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

  int  i = 1234;

  LONGPOINTER lp_buf = longaddr(buf);
  sprintf(outbuf,"space: 0x%08x, offset: 0x%08x\n",
                lp_buf.spaceid,lp_buf.offset);
  PRINT(longaddr(outbuf), -strlen(outbuf), 0);

  lp_buf = longaddr(&i);
  sprintf(outbuf,"peek of i: %d\n",longpeek(lp_buf));
  PRINT(longaddr(outbuf), -strlen(outbuf), 0);

  longpoke(lp_buf,4567);
  sprintf(outbuf,"poked i: %d\n",i);
  PRINT(longaddr(outbuf), -strlen(outbuf), 0);

  lp_buf = longaddr(buf1);
  sprintf(outbuf,"buf1 space: 0x%08x, offset: 0x%08x\n",
                lp_buf.spaceid,lp_buf.offset);
  PRINT(longaddr(outbuf), -strlen(outbuf), 0);

  longmove(strlen(buf1) + 1, longaddr(buf1), longaddr(buf));
  sprintf(outbuf,"moved buf: %s\n",buf);
  PRINT(longaddr(outbuf), -strlen(outbuf), 0);

  buf1 = "This is the second test!";
  move_fast(strlen(buf1) + 1, buf1, buf);
  sprintf(outbuf,"moved buf: %s\n",buf);
  PRINT(longaddr(outbuf), -strlen(outbuf), 0);
  };

and finally .... longpointer.h:

/*
 * gcc long pointer support code for HPPA.
 * Copyright 1998, DIS International, Ltd.
 * Permission is granted to use this code under the GNU LIBRARY GENERAL
 * PUBLIC LICENSE, Version 2, June 1991.
 */
typedef struct {
  int           spaceid;
  unsigned int  offset;
  } LONGPOINTER, longpointer;


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

  /*
   * The colons separate output from input parameters. In this case,
   * the output of the instruction (output indicated by the "=" in the
   * constraint) is to a memory location (indicated by the "m"). The
   * input constraint indicates that the source to the instruction
   * is a register reference (indicated by the "r").
   * The general format is:
   *   asm("<instruction template>" : <output> : <input> : <clobbers>);
   *     where <output> and <input> are:
   *       "<constraint>" (<token>)
   *     <instruction template> is the PA-RISC instruction in template fmt.
   *     <clobbers> indicates those registers clobbered by the instruction
   *     and provides hints to the optimizer.
   *
   * Refer to the gcc documentation or http://www.dis.com/gnu/gcc_toc.html
   */
  asm volatile (
      "comiclr,= 0,%1,%%r28;
         ldsid (%%r0,%1),%%r28;
       stw %%r28, %0"
                        : "=m" (val)    // Output to val
                        : "r" (source)  // Source must be gen reg
                        : "%r28");      // Clobbers %r28
  return (val);
  };

LONGPOINTER longaddr(void *source)
  {
  LONGPOINTER lptr;
  /*
   * Return the long pointer for the address in sr5 space.
   */

  asm volatile (
      "comiclr,= 0,%2,%%r28;
         ldsid (%%r0,%2),%%r28;
       stw %%r28, %0;
       stw %2, %1"
                        : "=m" (lptr.spaceid),
                          "=m" (lptr.offset)    // Store to lptr
                        : "r" (source)          // Source must be gen reg
                        : "%r28");      // Clobbers %r28
  return (lptr);
  };

LONGPOINTER addtopointer(LONGPOINTER source,    // %r26 == source offset
                                                // %r25 == source space
                        int             len)    // %r24 == length in bytes
  {
  /*
   * Increment a longpointer.
   */

  asm volatile (
      "copy %0,%%r28;                           // copy space to r28
       add %1,%2,%%r29"                         // Increment the pointer
                        :                       // No output
                        : "r" (source.spaceid), // Source address
                          "r" (source.offset),
                          "r" (len)             // Length
                        : "%r28",               // Clobbers
                          "%r29");
  };

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.
   */

  asm volatile (
      ".import $$lr_unk_unk_long,MILLICODE;
       mtsp %0,%%sr1;                           // copy source space to sr1
       copy %1,%%r26;                           // load source offset to r26
       copy %4,%%r24;                           // load length to r24
       copy %3,%%r25;                           // load target offset to r25
       bl $$lr_unk_unk_long,%%r31;              // start branch to millicode
       mtsp %2,%%sr2"                           // copy target space to sr2
                        :                       // No output
                        : "r" (source.spaceid), // Source address
                          "r" (source.offset),
                          "r" (target.spaceid), // Target address
                          "r" (target.offset),
                          "r" (len)             // Byte length
                        : "%r1",                // Clobbers
                          "%r24",
                          "%r25",
                          "%r26",
                          "%r31");
  };

int longpeek(LONGPOINTER source)
  {
  /*
   * Fetch the int in long pointer space.
   */
  unsigned int val;

  asm volatile (
      "mtsp %1, %%sr1;
       copy %2, %%r28;
       ldw 0(%%sr1, %%r28), %%r28;
       stw %%r28, %0"
                        : "=m" (val)            // Output val
                        : "r" (source.spaceid), // Source space ID
                          "r" (source.offset)   // Source offset
                        : "%r28");              // Clobbers %r28

  return (val);
  };

void longpoke(LONGPOINTER target,       // %r25 == spaceid, %r26 == offset
          unsigned int val)             // %r24 == value
  {
  /*
   * Store the val into long pointer space.
   */
  asm volatile (
      "mtsp %0,%%sr1;
       copy %1, %%r28;
       stw %2, 0(%%sr1, %%r28)"
                        :                       // No output
                        : "r" (target.spaceid), // Target space ID
                          "r" (target.offset),  // Target offset
                          "r" (val)             // Value to store
                        : "%r28"                // Clobbers %r28
                        );                      // Copy space to %sr1
  };

void move_fast(int len,                 // %r26 == byte length
               void *source,            // %r25 == source addr
               void *target)            // %r24 == target addr
  {
  /*
   * Move using short pointers.
   */
  asm volatile (
      ".import $$lr_unk_unk,MILLICODE;
       copy %1, %%r26;                          // Move source addr into pos
       copy %2, %%r25;                          // Move target addr into pos
       bl $$lr_unk_unk,%%r31;                   // Start branch to millicode
       copy %0, %%r24"                          // Move length into position
                        :                       // No output
                        : "r" (len),            // Byte length
                          "r" (source),         // Source address
                          "r" (target)          // Target address
                        : "%r24",               // Clobbers
                          "%r25",
                          "%r26",
                          "%r31");
  };

ATOM RSS1 RSS2