This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: lib/sort.t failure
[perl5.git] / mpeix / mpeix.c
CommitLineData
feb33499
JH
1
2/*
3 * gcc long pointer support code for HPPA.
4 * Copyright 1998, DIS International, Ltd.
5 * Permission is granted to use this code under the GNU LIBRARY GENERAL
6 * PUBLIC LICENSE, Version 2, June 1991.
7 */
8typedef struct {
9 int spaceid;
10 unsigned int offset;
11 } LONGPOINTER, longpointer;
12
13/*
14 * gcc long pointer support code for HPPA.
15 * Copyright 1998, DIS International, Ltd.
16 * Permission is granted to use this code under the GNU LIBRARY GENERAL
17 * PUBLIC LICENSE, Version 2, June 1991.
18 */
19
20int __perl_mpe_getspaceid(void *source)
21 {
22 int val;
23 /*
24 * Given the short pointer, determine it's space ID.
25 */
26
27 /*
28 * The colons separate output from input parameters. In this case,
29 * the output of the instruction (output indicated by the "=" in the
30 * constraint) is to a memory location (indicated by the "m"). The
31 * input constraint indicates that the source to the instruction
32 * is a register reference (indicated by the "r").
33 * The general format is:
34 * asm("<instruction template>" : <output> : <input> : <clobbers>);
35 * where <output> and <input> are:
36 * "<constraint>" (<token>)
37 * <instruction template> is the PA-RISC instruction in template fmt.
38 * <clobbers> indicates those registers clobbered by the instruction
39 * and provides hints to the optimizer.
40 *
41 * Refer to the gcc documentation or http://www.dis.com/gnu/gcc_toc.html
42 */
43 asm volatile (
44 "comiclr,= 0,%1,%%r28;
45 ldsid (%%r0,%1),%%r28;
46 stw %%r28, %0"
47 : "=m" (val) // Output to val
48 : "r" (source) // Source must be gen reg
49 : "%r28"); // Clobbers %r28
50 return (val);
51 };
52
53LONGPOINTER __perl_mpe_longaddr(void *source)
54 {
55 LONGPOINTER lptr;
56 /*
57 * Return the long pointer for the address in sr5 space.
58 */
59
60 asm volatile (
61 "comiclr,= 0,%2,%%r28;
62 ldsid (%%r0,%2),%%r28;
63 stw %%r28, %0;
64 stw %2, %1"
65 : "=m" (lptr.spaceid),
66 "=m" (lptr.offset) // Store to lptr
67 : "r" (source) // Source must be gen reg
68 : "%r28"); // Clobbers %r28
69 return (lptr);
70 };
71
72LONGPOINTER __perl_mpe_addtopointer(LONGPOINTER source, // %r26 == source offset
73 // %r25 == source space
74 int len) // %r24 == length in bytes
75 {
76 /*
77 * Increment a longpointer.
78 */
79
80 asm volatile (
81 "copy %0,%%r28; // copy space to r28
82 add %1,%2,%%r29" // Increment the pointer
83 : // No output
84 : "r" (source.spaceid), // Source address
85 "r" (source.offset),
86 "r" (len) // Length
87 : "%r28", // Clobbers
88 "%r29");
89 };
90
91void __perl_mpe_longmove(int len, // %r26 == byte length
92 LONGPOINTER source, // %r23 == source space, %r24 == off
93 LONGPOINTER target) // sp-#56 == target space, sp-#52== off
94 {
95 /*
96 * Move data between two buffers in long pointer space.
97 */
98
99 asm volatile (
100 ".import $$lr_unk_unk_long,MILLICODE;
101 mtsp %0,%%sr1; // copy source space to sr1
102 copy %1,%%r26; // load source offset to r26
103 copy %4,%%r24; // load length to r24
104 copy %3,%%r25; // load target offset to r25
105 bl $$lr_unk_unk_long,%%r31; // start branch to millicode
106 mtsp %2,%%sr2" // copy target space to sr2
107 : // No output
108 : "r" (source.spaceid), // Source address
109 "r" (source.offset),
110 "r" (target.spaceid), // Target address
111 "r" (target.offset),
112 "r" (len) // Byte length
113 : "%r1", // Clobbers
114 "%r24",
115 "%r25",
116 "%r26",
117 "%r31");
118 };
119
120int __perl_mpe_longpeek(LONGPOINTER source)
121 {
122 /*
123 * Fetch the int in long pointer space.
124 */
125 unsigned int val;
126
127 asm volatile (
128 "mtsp %1, %%sr1;
129 copy %2, %%r28;
130 ldw 0(%%sr1, %%r28), %%r28;
131 stw %%r28, %0"
132 : "=m" (val) // Output val
133 : "r" (source.spaceid), // Source space ID
134 "r" (source.offset) // Source offset
135 : "%r28"); // Clobbers %r28
136
137 return (val);
138 };
139
140void __perl_mpe_longpoke(LONGPOINTER target, // %r25 == spaceid, %r26 == offset
141 unsigned int val) // %r24 == value
142 {
143 /*
144 * Store the val into long pointer space.
145 */
146 asm volatile (
147 "mtsp %0,%%sr1;
148 copy %1, %%r28;
149 stw %2, 0(%%sr1, %%r28)"
150 : // No output
151 : "r" (target.spaceid), // Target space ID
152 "r" (target.offset), // Target offset
153 "r" (val) // Value to store
154 : "%r28" // Clobbers %r28
155 ); // Copy space to %sr1
156 };
157
158void __perl_mpe_move_fast(int len, // %r26 == byte length
159 void *source, // %r25 == source addr
160 void *target) // %r24 == target addr
161 {
162 /*
163 * Move using short pointers.
164 */
165 asm volatile (
166 ".import $$lr_unk_unk,MILLICODE;
167 copy %1, %%r26; // Move source addr into pos
168 copy %2, %%r25; // Move target addr into pos
169 bl $$lr_unk_unk,%%r31; // Start branch to millicode
170 copy %0, %%r24" // Move length into position
171 : // No output
172 : "r" (len), // Byte length
173 "r" (source), // Source address
174 "r" (target) // Target address
175 : "%r24", // Clobbers
176 "%r25",
177 "%r26",
178 "%r31");
179 };
180
181/*
182 * ftruncate - set file size, BSD Style
183 *
184 * shortens or enlarges the file as neeeded
185 * uses some undocumented locking call. It is known to work on SCO unix,
186 * other vendors should try.
187 * The #error directive prevents unsupported OSes
188 */
189
190#include <unistd.h>
191#include <errno.h>
192#include <fcntl.h>
193#include <stdio.h>
194#include <mpe.h>
195
196extern void FCONTROL(short, short, longpointer);
197extern void PRINTFILEINFO(int);
198
199int ftruncate(int fd, long wantsize);
200
201int ftruncate(int fd, long wantsize) {
202
203int ccode_return,dummy=0;
204
205if (lseek(fd, wantsize, SEEK_SET) < 0) {
206 return (-1);
207}
208
209FCONTROL(_mpe_fileno(fd),6,__perl_mpe_longaddr(&dummy)); /* Write new EOF */
210if ((ccode_return=ccode()) != CCE) {
211 fprintf(stderr,"MPE ftruncate failed, ccode=%d, wantsize=%ld\n",ccode_return,wantsize);
212 PRINTFILEINFO(_mpe_fileno(fd));
213 errno = ESYSERR;
214 return (-1);
215}
216
217return (0);
218}
219
220/*
221 wrapper for truncate():
222
223 truncate() is UNIX, not POSIX.
224
225 This function requires ftruncate().
226
227
228
229 NAME
230 truncate -
231
232 SYNOPSIS
233 #include <unistd.h>
234
235 int truncate(const char *pathname, off_t length);
236
237 Returns: 0 if OK, -1 on error
238
239 from: Stevens' Advanced Programming in the UNIX Environment, p. 92
240
241
242
243 ERRORS
244 EACCES
245 EBADF
246 EDQUOT (not POSIX) <- not implemented here
247 EFAULT
248 EINVAL
249 EISDIR
250 ELOOP (not POSIX) <- not implemented here
251 ENAMETOOLONG
252 ENOTDIR
253 EROFS
254 ETXTBSY (not POSIX) <- not implemented here
255
256 from: HP-UX man page
257
258
259
260 Compile directives:
261 PRINT_ERROR - make this function print an error message to stderr
262*/
263
264#ifndef _POSIX_SOURCE
265# define _POSIX_SOURCE
266#endif
267
268#include <sys/types.h> /* off_t, required by open() */
269#include <sys/stat.h> /* required by open() */
270#include <fcntl.h> /* open() */
271#include <unistd.h> /* close() */
272#include <stdio.h> /* perror(), sprintf() */
273
274
275
276int
277truncate(const char *pathname, off_t length)
278{
279 int fd;
280#ifdef PRINT_ERROR
281 char error_msg[80+1];
282#endif
283
284 if (length == 0)
285 {
286 if ( (fd = open(pathname, O_WRONLY | O_TRUNC)) < 0)
287 {
288 /* errno already set */
289#ifdef PRINT_ERROR
290 sprintf(error_msg,
291 "truncate(): open(%s, O_WRONLY | OTRUNC)\0",
292 pathname);
293 perror(error_msg);
294#endif
295 return -1;
296 }
297 }
298 else
299 {
300 if ( (fd = open(pathname, O_WRONLY)) < 0)
301 {
302 /* errno already set */
303#ifdef PRINT_ERROR
304 sprintf(error_msg,
305 "truncate(): open(%s, O_WRONLY)\0",
306 pathname);
307 perror(error_msg);
308#endif
309 return -1;
310 }
311
312 if (ftruncate(fd, length) < 0)
313 {
314 /* errno already set */
315#ifdef PRINT_ERROR
316 perror("truncate(): ftruncate()");
317#endif
318 return -1;
319 }
320 }
321
322 if (close(fd) < 0)
323 {
324 /* errno already set */
325#ifdef PRINT_ERROR
326 perror("truncate(): close()");
327#endif
328 return -1;
329 }
330
331 return 0;
332} /* truncate() */
333
334/*
335 wrapper for gettimeofday():
336 gettimeofday() is UNIX, not POSIX.
337 gettimeofday() is a BSD function.
338
339
340
341 NAME
342 gettimeofday -
343
344 SYNOPSIS
345 #include <sys/time.h>
346
347 int gettimeofday(struct timeval *tp, struct timezone *tzp);
348
349 DESCRIPTION
350 This function returns seconds and microseconds since midnight
351 January 1, 1970. The microseconds is actually only accurate to
352 the millisecond.
353
354 Note: To pick up the definitions of structs timeval and timezone
355 from the <time.h> include file, the directive
356 _SOCKET_SOURCE must be used.
357
358 RETURN VALUE
359 A 0 return value indicates that the call succeeded. A -1 return
360 value indicates an error occurred; errno is set to indicate the
361 error.
362
363 ERRORS
364 EFAULT not implemented
365
366 Changes:
367 2-91 DR. Created.
368*/
369
370
371/* need _SOCKET_SOURCE to pick up structs timeval and timezone in time.h */
372#ifndef _SOCKET_SOURCE
373# define _SOCKET_SOURCE
374#endif
375
376#include <time.h> /* structs timeval & timezone,
377 difftime(), localtime(), mktime(), time() */
378#include <sys/time.h> /* gettimeofday() */
379
380extern int TIMER();
381
382
383
384#ifdef __STDC__
385int gettimeofday( struct timeval *tp, struct timezone *tpz )
386#else
387int gettimeofday( tp, tpz )
388struct timeval *tp;
389struct timezone *tpz;
390#endif
391{
392 static unsigned long basetime = 0;
393 static int dsttime = 0;
394 static int minuteswest = 0;
395 static int oldtime = 0;
396 register int newtime;
397
398
399 /*-------------------------------------------------------------------*/
400 /* Setup a base from which all future time will be computed. */
401 /*-------------------------------------------------------------------*/
402 if ( basetime == 0 )
403 {
404 time_t gmt_time;
405 time_t loc_time;
406 struct tm *loc_time_tm;
407
408 gmt_time = time( NULL );
409 loc_time_tm = localtime( &gmt_time ) ;
410 loc_time = mktime( loc_time_tm );
411
412 oldtime = TIMER();
413 basetime = (unsigned long) ( loc_time - (oldtime/1000) );
414
415 /*----------------------------------------------------------------*/
416 /* The calling process must be restarted if timezone or dst */
417 /* changes. */
418 /*----------------------------------------------------------------*/
419 minuteswest = (int) (difftime( loc_time, gmt_time ) / 60);
420 dsttime = loc_time_tm->tm_isdst;
421 }
422
423 /*-------------------------------------------------------------------*/
424 /* Get the new time value. The timer value rolls over every 24 days, */
425 /* so if the delta is negative, the basetime value is adjusted. */
426 /*-------------------------------------------------------------------*/
427 newtime = TIMER();
428 if ( newtime < oldtime ) basetime += 2073600;
429 oldtime = newtime;
430
431 /*-------------------------------------------------------------------*/
432 /* Return the timestamp info. */
433 /*-------------------------------------------------------------------*/
434 tp->tv_sec = basetime + newtime/1000;
435 tp->tv_usec = (newtime%1000) * 1000; /* only accurate to milli */
436 if (tpz)
437 {
438 tpz->tz_minuteswest = minuteswest;
439 tpz->tz_dsttime = dsttime;
440 }
441
442 return 0;
443
444} /* gettimeofday() */