3 * gcc long pointer support code for HPPA.
4 * Copyright 1998, DIS International, Ltd.
5 * This code is free software; you may redistribute it and/or modify
6 * it under the same terms as Perl itself. (Relicensed for Perl in
7 * in April 2002 by Mark Klein.)
12 } LONGPOINTER, longpointer;
15 * gcc long pointer support code for HPPA.
16 * Copyright 1998, DIS International, Ltd.
17 * This code is free software; you may redistribute it and/or modify
18 * it under the same terms as Perl itself. (Relicensed for Perl in
19 * in April 2002 by Mark Klein.)
22 int __perl_mpe_getspaceid(void *source)
26 * Given the short pointer, determine it's space ID.
30 * The colons separate output from input parameters. In this case,
31 * the output of the instruction (output indicated by the "=" in the
32 * constraint) is to a memory location (indicated by the "m"). The
33 * input constraint indicates that the source to the instruction
34 * is a register reference (indicated by the "r").
35 * The general format is:
36 * asm("<instruction template>" : <output> : <input> : <clobbers>);
37 * where <output> and <input> are:
38 * "<constraint>" (<token>)
39 * <instruction template> is the PA-RISC instruction in template fmt.
40 * <clobbers> indicates those registers clobbered by the instruction
41 * and provides hints to the optimizer.
43 * Refer to the gcc documentation or http://www.dis.com/gnu/gcc_toc.html
45 __asm__ __volatile__ (
46 " comiclr,= 0,%1,%%r28\n"
47 "\t ldsid (%%r0,%1),%%r28\n"
49 : "=m" (val) // Output to val
50 : "r" (source) // Source must be gen reg
51 : "%r28"); // Clobbers %r28
55 LONGPOINTER __perl_mpe_longaddr(void *source)
59 * Return the long pointer for the address in sr5 space.
62 __asm__ __volatile__ (
63 " comiclr,= 0,%2,%%r28\n"
64 "\t ldsid (%%r0,%2),%%r28\n"
67 : "=m" (lptr.spaceid),
68 "=m" (lptr.offset) // Store to lptr
69 : "r" (source) // Source must be gen reg
70 : "%r28"); // Clobbers %r28
74 LONGPOINTER __perl_mpe_addtopointer(LONGPOINTER source, // %r26 == source offset
75 // %r25 == source space
76 int len) // %r24 == length in bytes
79 * Increment a longpointer.
82 __asm__ __volatile__ (
83 " copy %0,%%r28\n" // copy space to r28
84 "\t add %1,%2,%%r29" // Increment the pointer
86 : "r" (source.spaceid), // Source address
93 void __perl_mpe_longmove(int len, // %r26 == byte length
94 LONGPOINTER source, // %r23 == source space, %r24 == off
95 LONGPOINTER target) // sp-#56 == target space, sp-#52== off
98 * Move data between two buffers in long pointer space.
101 __asm__ __volatile__ (
102 " .import $$lr_unk_unk_long,MILLICODE\n"
103 "\t mtsp %0,%%sr1\n" // copy source space to sr1
104 "\t copy %1,%%r26\n" // load source offset to r26
105 "\t copy %4,%%r24\n" // load length to r24
106 "\t copy %3,%%r25\n" // load target offset to r25
107 "\t bl $$lr_unk_unk_long,%%r31\n" // start branch to millicode
108 "\t mtsp %2,%%sr2" // copy target space to sr2
110 : "r" (source.spaceid), // Source address
112 "r" (target.spaceid), // Target address
114 "r" (len) // Byte length
122 int __perl_mpe_longpeek(LONGPOINTER source)
125 * Fetch the int in long pointer space.
129 __asm__ __volatile__ (
131 "\t copy %2, %%r28\n"
132 "\t ldw 0(%%sr1, %%r28), %%r28\n"
134 : "=m" (val) // Output val
135 : "r" (source.spaceid), // Source space ID
136 "r" (source.offset) // Source offset
137 : "%r28"); // Clobbers %r28
142 void __perl_mpe_longpoke(LONGPOINTER target, // %r25 == spaceid, %r26 == offset
143 unsigned int val) // %r24 == value
146 * Store the val into long pointer space.
148 __asm__ __volatile__ (
150 "\t copy %1, %%r28\n"
151 "\t stw %2, 0(%%sr1, %%r28)"
153 : "r" (target.spaceid), // Target space ID
154 "r" (target.offset), // Target offset
155 "r" (val) // Value to store
156 : "%r28" // Clobbers %r28
157 ); // Copy space to %sr1
160 void __perl_mpe_move_fast(int len, // %r26 == byte length
161 void *source, // %r25 == source addr
162 void *target) // %r24 == target addr
165 * Move using short pointers.
167 __asm__ __volatile__ (
168 " .import $$lr_unk_unk,MILLICODE\n"
169 "\t copy %1, %%r26\n" // Move source addr into pos
170 "\t copy %2, %%r25\n" // Move target addr into pos
171 "\t bl $$lr_unk_unk,%%r31\n" // Start branch to millicode
172 "\t copy %0, %%r24" // Move length into position
174 : "r" (len), // Byte length
175 "r" (source), // Source address
176 "r" (target) // Target address
177 : "%r24", // Clobbers
184 * ftruncate - set file size, BSD Style
186 * shortens or enlarges the file as neeeded
187 * uses some undocumented locking call. It is known to work on SCO unix,
188 * other vendors should try.
189 * The #error directive prevents unsupported OSes
191 * ftruncate/truncate code by Mark Bixby.
192 * This code is free software; you may redistribute it and/or modify
193 * it under the same terms as Perl itself.
203 extern void FCONTROL(short, short, longpointer);
204 extern void PRINTFILEINFO(int);
206 int ftruncate(int fd, long wantsize);
208 int ftruncate(int fd, long wantsize) {
210 int ccode_return,dummy=0;
212 if (lseek(fd, wantsize, SEEK_SET) < 0) {
216 FCONTROL(_mpe_fileno(fd),6,__perl_mpe_longaddr(&dummy)); /* Write new EOF */
217 if ((ccode_return=ccode()) != CCE) {
218 fprintf(stderr,"MPE ftruncate failed, ccode=%d, wantsize=%ld\n",ccode_return,wantsize);
219 PRINTFILEINFO(_mpe_fileno(fd));
228 wrapper for truncate():
230 truncate() is UNIX, not POSIX.
232 This function requires ftruncate().
242 int truncate(const char *pathname, off_t length);
244 Returns: 0 if OK, -1 on error
246 from: Stevens' Advanced Programming in the UNIX Environment, p. 92
253 EDQUOT (not POSIX) <- not implemented here
257 ELOOP (not POSIX) <- not implemented here
261 ETXTBSY (not POSIX) <- not implemented here
268 PRINT_ERROR - make this function print an error message to stderr
271 #ifndef _POSIX_SOURCE
272 # define _POSIX_SOURCE
275 #include <sys/types.h> /* off_t, required by open() */
276 #include <sys/stat.h> /* required by open() */
277 #include <fcntl.h> /* open() */
278 #include <unistd.h> /* close() */
279 #include <stdio.h> /* perror(), sprintf() */
284 truncate(const char *pathname, off_t length)
288 char error_msg[80+1];
293 if ( (fd = open(pathname, O_WRONLY | O_TRUNC)) < 0)
295 /* errno already set */
298 "truncate(): open(%s, O_WRONLY | OTRUNC)\0",
307 if ( (fd = open(pathname, O_WRONLY)) < 0)
309 /* errno already set */
312 "truncate(): open(%s, O_WRONLY)\0",
319 if (ftruncate(fd, length) < 0)
321 /* errno already set */
323 perror("truncate(): ftruncate()");
331 /* errno already set */
333 perror("truncate(): close()");
342 wrapper for gettimeofday():
343 gettimeofday() is UNIX, not POSIX.
344 gettimeofday() is a BSD function.
350 #include <sys/time.h>
352 int gettimeofday(struct timeval *tp, struct timezone *tzp);
355 This function returns seconds and microseconds since midnight
356 January 1, 1970. The microseconds is actually only accurate to
359 Note: To pick up the definitions of structs timeval and timezone
360 from the <time.h> include file, the directive
361 _SOCKET_SOURCE must be used.
364 A 0 return value indicates that the call succeeded. A -1 return
365 value indicates an error occurred; errno is set to indicate the
369 EFAULT not implemented
376 /* need _SOCKET_SOURCE to pick up structs timeval and timezone in time.h */
377 #ifndef _SOCKET_SOURCE
378 # define _SOCKET_SOURCE
381 #include <time.h> /* structs timeval & timezone,
382 difftime(), localtime(), mktime(), time() */
383 #include <sys/time.h> /* gettimeofday() */
388 * gettimeofday code by Mark Bixby.
389 * This code is free software; you may redistribute it and/or modify
390 * it under the same terms as Perl itself.
394 int gettimeofday( struct timeval *tp, struct timezone *tpz )
396 int gettimeofday( tp, tpz )
398 struct timezone *tpz;
401 static unsigned long basetime = 0;
402 static int dsttime = 0;
403 static int minuteswest = 0;
404 static int oldtime = 0;
405 register int newtime;
408 /*-------------------------------------------------------------------*/
409 /* Setup a base from which all future time will be computed. */
410 /*-------------------------------------------------------------------*/
415 struct tm *loc_time_tm;
417 gmt_time = time( NULL );
418 loc_time_tm = localtime( &gmt_time ) ;
419 loc_time = mktime( loc_time_tm );
422 basetime = (unsigned long) ( loc_time - (oldtime/1000) );
424 /*----------------------------------------------------------------*/
425 /* The calling process must be restarted if timezone or dst */
427 /*----------------------------------------------------------------*/
428 minuteswest = (int) (difftime( loc_time, gmt_time ) / 60);
429 dsttime = loc_time_tm->tm_isdst;
432 /*-------------------------------------------------------------------*/
433 /* Get the new time value. The timer value rolls over every 24 days, */
434 /* so if the delta is negative, the basetime value is adjusted. */
435 /*-------------------------------------------------------------------*/
437 if ( newtime < oldtime ) basetime += 2073600;
440 /*-------------------------------------------------------------------*/
441 /* Return the timestamp info. */
442 /*-------------------------------------------------------------------*/
443 tp->tv_sec = basetime + newtime/1000;
444 tp->tv_usec = (newtime%1000) * 1000; /* only accurate to milli */
447 tpz->tz_minuteswest = minuteswest;
448 tpz->tz_dsttime = dsttime;
453 } /* gettimeofday() */
456 ** MPE_FCNTL -- shadow function for fcntl()
458 ** MPE requires sfcntl() for sockets, and fcntl() for everything
459 ** else. This shadow routine determines the descriptor type and
460 ** makes the appropriate call.
470 #include <sys/socket.h>
473 mpe_fcntl(int fildes, int cmd, ...)
482 arg = va_arg(ap, void *);
486 if (getsockname(fildes, &sa, &len) == -1)
488 if (errno == EAFNOSUPPORT)
490 return sfcntl(fildes, cmd, arg);
492 if (errno == ENOTSOCK)
494 return fcntl(fildes, cmd, arg);
496 /* unknown getsockname() failure */
502 if ((result = sfcntl(fildes, cmd, arg)) != -1 && cmd == F_GETFL)
503 result |= O_RDWR; /* fill in some missing flags */