HP3000-L Archives

October 1996, Week 2

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:
Sat, 12 Oct 1996 11:00:51 -0700
Content-Type:
text/plain
Parts/Attachments:
text/plain (177 lines)
I've recently had a rash of requests about using gcc/g++ with long
pointers. I thought the best thing to do would be to provide a sample
set of the routines I use and include some narrative. Those not using
gcc/g++, hit <delete> now!

Below are a group of routines that I've implemented to make use of
long pointers. While I've not yet figured out a way to make them as
seamless as they are in HP/C by use of the ^ operator in gcc, I'm
currently playing with a class library with overlayed operators that
just might make long pointers seamless in g++. I'll follow up on that
in another post.

This example demonstrates the use of long pointers for stuff in the stack
frame. However, obtaining a long pointer (HPFOPEN, FFILEINFO, et. al.) to
some object in long pointer space and then using the move and peek and poke
routines will work. They can also be expanded upon fairly easily. The only
real confusing routine is longmove. This is because not all parameters will
fit in registers. In such a case, the compiler generates different code
depending on whether or not the optimizer is enabled. As such, the stack
offsets are different in each case and the data needs to be in a known
location for the assembly to work.

Read the GCC manual (http://www.dis.com/gnu/gcc_toc.html) for details about
the 'asm' extension. The format is:

asm(<instruction template> : <output parms> : <input parms>)

Where <instruction template> is a PA-RISC instruction with operands inserted.
The operands are %0-%9 and are positional in <output parms> and <input parms>.
<output parms> and <input parms> are:

"<constraint>" (<variable>)

The <constraint> is documented in the manual. But, the main ones of interest
are "r" for a register, "m" for a memory reference, "g" for either. The
<variable>
is a symbol which is referenced within the code. So, the template:

asm("ldw %%r26,%0" : /* no output parms */ : "m" (myvar));

will generate the instruction "ldw %r26,-100(%r0,%r30)" if myvar is in the
frame at
sp-100.



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 %r26. This is actually a
   * short to long conversion, but returns it to the struct LONGPOINTER.
   */

  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
  {
  /*
   * Fast 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
  };

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

  int  i = 1234;

  LONGPOINTER lp_buf = longaddr(buf);
  printf("space: 0x%08x, offset: 0x%08x\n",lp_buf.spaceid,lp_buf.offset);

  lp_buf = longaddr(&i);
  printf("peek of i: %d\n",longpeek(lp_buf));

  longpoke(lp_buf,4567);
  printf("poked i: %d\n",i);

  lp_buf = longaddr(buf1);
  printf("buf1 space: 0x%08x, offset: 0x%08x\n",lp_buf.spaceid,lp_buf.offset);

  longmove(strlen(buf1) + 1, longaddr(buf1), longaddr(buf));
  printf("moved buf: %s\n",buf);

  buf1 = "This is the second test!";
  move_fast(strlen(buf1) + 1, buf1, buf);
  printf("moved buf: %s\n",buf);
  };
Mark Klein                                              DIS International, Ltd.
http://www.dis.com                                      415-892-8400

ATOM RSS1 RSS2