Commit | Line | Data |
---|---|---|
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 | */ | |
8 | typedef 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 | ||
20 | int __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 | ||
53 | LONGPOINTER __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 | ||
72 | LONGPOINTER __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 | ||
91 | void __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 | ||
120 | int __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 | ||
140 | void __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 | ||
158 | void __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 | ||
196 | extern void FCONTROL(short, short, longpointer); | |
197 | extern void PRINTFILEINFO(int); | |
198 | ||
199 | int ftruncate(int fd, long wantsize); | |
200 | ||
201 | int ftruncate(int fd, long wantsize) { | |
202 | ||
203 | int ccode_return,dummy=0; | |
204 | ||
205 | if (lseek(fd, wantsize, SEEK_SET) < 0) { | |
206 | return (-1); | |
207 | } | |
208 | ||
209 | FCONTROL(_mpe_fileno(fd),6,__perl_mpe_longaddr(&dummy)); /* Write new EOF */ | |
210 | if ((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 | ||
217 | return (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 | ||
276 | int | |
277 | truncate(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 | ||
380 | extern int TIMER(); | |
381 | ||
382 | ||
383 | ||
384 | #ifdef __STDC__ | |
385 | int gettimeofday( struct timeval *tp, struct timezone *tpz ) | |
386 | #else | |
387 | int gettimeofday( tp, tpz ) | |
388 | struct timeval *tp; | |
389 | struct 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() */ |