HP3000-L Archives

November 1996, 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:
Tue, 5 Nov 1996 13:17:18 -0800
Content-Type:
text/plain
Parts/Attachments:
text/plain (184 lines)
Michael Anderson asks:

>How to get the CCE, CCG, CCL condition code using the GNU C compiler?

>Can both of these compilers be used directly from the MPE CI prompt,
>or is the POSIX shell required?

When I ported gcc, it was with the intention that it would use the POSIX
library (/lib/libc.a) or native C (LIBC.LIB.SYS) library and not directly
call intrinsics. However, calling intrinsics is possible. A couple of weeks
ago I posted a group of routines that will assist in this endeavor. I've
included them below again with another example.

First off, many parameters to the intrinsics are long pointers. Since
gcc doesn't directly know about long pointers (nor does it know about
intrinsics), you'll have to build wrappers that will construct the long
pointers and then invoke the real intrinsic. I've thought about building
a complete library like this for a long time, but I've been too busy just
doing the necessary parts of the port that I haven't had time to go back.

In any event, I'll give you an example (marginally tested) using the PRINT
intrinsic. I'll also include in the example the method for obtaining the
condition code in order to directly answer the poster's question.

Secondly, can the compiler be invoked directly from the CI prompt? Yes,
it can, but it will use POSIX semantics. In other words, all names will be
interpreted as if you were running under the shell.

Now for the example:

Using Stan's CSEQ (available from Lund), you can get the calling sequence
for the PRINT intrinsic:

Procedure PRINT (
   message      : anyvar record  ;        {R25, R26}
                                          {Address type = LongAddr}
   length       :        int16   ;        {R24}
   control      :        int16   )        {R23}
      uncheckable_anyvar

Note that the message is a long pointer. Using the routines included
below, you can construct a long pointer by yourself and then call
the intrinsic. Note that most intrinsics are all UPPERCASE. So,
the PRINT intrinsic is not the same as the print() function. Further,
ccode() is actually CCODE(). (Or you can alternately use HPGETCCODE).

You may not need to understand all the goo below, but take note of the
LONGPOINTER declaration and longaddr() procedure. With these two pieces,
you should be able to call any intrinsic:

--- cut here ---

/*
 * Copyright, 1996 DIS International, Ltd. Permission is hereby given
 * to use this source code according to the GNU General Public License
 * as long as this copyright notice is also maintained intact.
 */

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
  };

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

  extern int    CCODE();

  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);
  };


--- cut here ---
Mark Klein                                              DIS International, Ltd.
http://www.dis.com                                      415-892-8400

ATOM RSS1 RSS2