OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [fp/] [implementation/] [mmix/] [mmix-io.w] - Blame information for rev 15

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 hellwig
% This file is part of the MMIXware package (c) Donald E Knuth 1999
2
@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES!
3
 
4
\def\title{MMIX-IO}
5
\def\MMIX{\.{MMIX}}
6
\def\Hex#1{\hbox{$^{\scriptscriptstyle\#}$\tt#1}} % experimental hex constant
7
 
8
@*Introduction. This program module contains brute-force implementations
9
of the ten input/output primitives defined at the beginning of {\mc MMIX-SIM}.
10
The subroutines are grouped here as a separate package, because they
11
are intended to be loaded with the pipeline simulator as well as with the
12
simple simulator.
13
@^I/O@>
14
@^input/output@>
15
 
16
@c
17
@@;
18
@@;
19
@@;
20
@@;
21
@@;
22
 
23
@ Of course we include standard \CEE/ library routines, and we set things
24
up to accommodate older versions of \CEE/.
25
 
26
@=
27
#include 
28
#include 
29
#ifdef __STDC__
30
#define ARGS(list) list
31
#else
32
#define ARGS(list) ()
33
#endif
34
#ifndef FILENAME_MAX
35
#define FILENAME_MAX 256
36
#endif
37
#ifndef SEEK_SET
38
#define SEEK_SET 0
39
#endif
40
#ifndef SEEK_END
41
#define SEEK_END 2
42
#endif
43
 
44
@ The unsigned 32-bit type \&{tetra} must agree with its definition
45
in the simulators.
46
 
47
@=
48
typedef unsigned int tetra;
49
typedef struct {tetra h,l;} octa; /* two tetrabytes make one octabyte */
50
 
51
@ Three basic subroutines are used to get strings from the simulated
52
memory and to put strings into that memory. These subroutines are
53
defined appropriately in each simulator. We also use a few subroutines
54
and constants defined in {\mc MMIX-ARITH}.
55
 
56
@=
57
extern char stdin_chr @,@,@[ARGS((void))@];
58
extern int mmgetchars @,@,@[ARGS((char* buf,int size,octa addr,int stop))@];
59
extern void mmputchars @,@,@[ARGS((unsigned char* buf,int size,octa addr))@];
60
extern octa oplus @,@,@[ARGS((octa,octa))@];
61
extern octa ominus @,@,@[ARGS((octa,octa))@];
62
extern octa incr @,@,@[ARGS((octa,int))@];
63
extern octa zero_octa; /* |zero_octa.h=zero_octa.l=0| */
64
extern octa neg_one; /* |neg_one.h=neg_one.l=-1| */
65
 
66
@ Each possible handle has a file pointer and a current mode.
67
 
68
@=
69
typedef struct {
70
  FILE *fp; /* file pointer */
71
  int mode; /* [read OK] + 2[write OK] + 4[binary] + 8[readwrite] */
72
} sim_file_info;
73
 
74
@ @=
75
sim_file_info sfile[256];
76
 
77
@ The first three handles are initially open.
78
 
79
@=
80
void mmix_io_init @,@,@[ARGS((void))@];@+@t}\6{@>
81
void mmix_io_init()
82
{
83
  sfile[0].fp=stdin, sfile[0].mode=1;
84
  sfile[1].fp=stdout, sfile[1].mode=2;
85
  sfile[2].fp=stderr, sfile[2].mode=2;
86
}
87
 
88
@ The only tricky thing about these routines is that we want to
89
protect the standard input, output, and error streams from being
90
preempted.
91
 
92
@=
93
octa mmix_fopen @,@,@[ARGS((unsigned char,octa,octa))@];@+@t}\6{@>
94
octa mmix_fopen(handle,name,mode)
95
  unsigned char handle;
96
  octa name,mode;
97
{
98
  char name_buf[FILENAME_MAX];
99
  if (mode.h || mode.l>4) goto abort;
100
  if (mmgetchars(name_buf,FILENAME_MAX,name,0)==FILENAME_MAX) goto abort;
101
  if (sfile[handle].mode!=0 && handle>2) fclose(sfile[handle].fp);
102
  sfile[handle].fp=fopen(name_buf,mode_string[mode.l]);
103
  if (!sfile[handle].fp) goto abort;
104
  sfile[handle].mode=mode_code[mode.l];
105
  return zero_octa; /* success */
106
 abort: sfile[handle].mode=0;
107
  return neg_one; /* failure */
108
}
109
 
110
@ @=
111
char *mode_string[]={"r","w","rb","wb","w+b"};
112
int mode_code[]={0x1,0x2,0x5,0x6,0xf};
113
 
114
@ If the simulator is being used interactively, we can avoid competition
115
for |stdin| by substituting another file.
116
 
117
@=
118
void mmix_fake_stdin @,@,@[ARGS((FILE*))@];@+@t}\6{@>
119
void mmix_fake_stdin(f)
120
  FILE *f;
121
{
122
  sfile[0].fp=f; /* |f| should be open in mode \.{"r"} */
123
}
124
 
125
@ @=
126
octa mmix_fclose @,@,@[ARGS((unsigned char))@];@+@t}\6{@>
127
octa mmix_fclose(handle)
128
  unsigned char handle;
129
{
130
  if (sfile[handle].mode==0) return neg_one;
131
  if (handle>2 && fclose(sfile[handle].fp)!=0) return neg_one;
132
  sfile[handle].mode=0;
133
  return zero_octa; /* success */
134
}
135
 
136
@ @=
137
octa mmix_fread @,@,@[ARGS((unsigned char,octa,octa))@];@+@t}\6{@>
138
octa mmix_fread(handle,buffer,size)
139
  unsigned char handle;
140
  octa buffer,size;
141
{
142
  register unsigned char *buf;
143
  register int n;
144
  octa o;
145
  o=neg_one;
146
  if (!(sfile[handle].mode&0x1)) goto done;
147
  if (sfile[handle].mode&0x8) sfile[handle].mode &=~ 0x2;
148
  if (size.h) goto done;
149
  buf=(unsigned char*)calloc(size.l,sizeof(char));
150
  if (!buf) goto done;
151
  @;
152
  mmputchars(buf,n,buffer);
153
  free(buf);
154
  o.h=0, o.l=n;
155
done: return ominus(o,size);
156
}
157
 
158
@ @=
159
if (sfile[handle].fp==stdin) {
160
  register unsigned char *p;
161
  for (p=buf,n=size.l; p
162
} else {
163
  clearerr(sfile[handle].fp);
164
  n=fread(buf,1,size.l,sfile[handle].fp);
165
  if (ferror(sfile[handle].fp)) {
166
    free(buf);
167
    goto done;
168
  }
169
}
170
 
171
@ @=
172
octa mmix_fgets @,@,@[ARGS((unsigned char,octa,octa))@];@+@t}\6{@>
173
octa mmix_fgets(handle,buffer,size)
174
  unsigned char handle;
175
  octa buffer,size;
176
{
177
  char buf[256];
178
  register int n,s;
179
  register char *p;
180
  octa o;
181
  int eof=0;
182
  if (!(sfile[handle].mode&0x1)) return neg_one;
183
  if (!size.l && !size.h) return neg_one;
184
  if (sfile[handle].mode&0x8) sfile[handle].mode &=~ 0x2;
185
  size=incr(size,-1);
186
  o=zero_octa;
187
  while (1) {
188
    @;
189
    mmputchars(buf,n+1,buffer);
190
    o=incr(o,n);
191
    size=incr(size,-n);
192
    if ((n&&buf[n-1]=='\n') || (!size.l&&!size.h) || eof) return o;
193
    buffer=incr(buffer,n);
194
  }
195
}
196
 
197
@ @=
198
s=255;
199
if (size.l
200
if (sfile[handle].fp==stdin)
201
  for (p=buf,n=0;n
202
    *p=stdin_chr();
203
    n++;
204
    if (*p++=='\n') break;
205
  }
206
else {
207
  if (!fgets(buf,s+1,sfile[handle].fp)) return neg_one;
208
  eof=feof(sfile[handle].fp);
209
  for (p=buf,n=0;n
210
    if (!*p && eof) break;
211
    n++;
212
    if (*p++=='\n') break;
213
  }
214
}
215
*p='\0';
216
 
217
@ The routines that deal with wyde characters might need to be
218
changed on a system that is little-endian; the author wishes
219
good luck to whoever has to do this.
220
\MMIX\ is always big-endian, but external files
221
prepared on random operating systems might be backwards.
222
@^little-endian versus big-endian@>
223
@^big-endian versus little-endian@>
224
@^system dependencies@>
225
 
226
@=
227
octa mmix_fgetws @,@,@[ARGS((unsigned char,octa,octa))@];@+@t}\6{@>
228
octa mmix_fgetws(handle,buffer,size)
229
  unsigned char handle;
230
  octa buffer,size;
231
{
232
  char buf[256];
233
  register int n,s;
234
  register char *p;
235
  octa o;
236
  int eof;
237
  if (!(sfile[handle].mode&0x1)) return neg_one;
238
  if (!size.l && !size.h) return neg_one;
239
  if (sfile[handle].mode&0x8) sfile[handle].mode &=~ 0x2;
240
  buffer.l&=-2;
241
  size=incr(size,-1);
242
  o=zero_octa;
243
  while (1) {
244
    @;
245
    mmputchars(buf,2*n+2,buffer);
246
    o=incr(o,n);
247
    size=incr(size,-n);
248
    if ((n&&buf[2*n-1]=='\n'&&buf[2*n-2]==0) || (!size.l&&!size.h) || eof)
249
      return o;
250
    buffer=incr(buffer,2*n);
251
  }
252
}
253
 
254
@ @=
255
s=127;
256
if (size.l
257
if (sfile[handle].fp==stdin)
258
  for (p=buf,n=0;n
259
    *p++=stdin_chr();@+*p++=stdin_chr();
260
    n++;
261
    if (*(p-1)=='\n' && *(p-2)==0) break;
262
  }
263
else for (p=buf,n=0;n
264
  if (fread(p,1,2,sfile[handle].fp)!=2) {
265
    eof=feof(sfile[handle].fp);
266
    if (!eof) return neg_one;
267
    break;
268
  }
269
  n++,p+=2;
270
    if (*(p-1)=='\n' && *(p-2)==0) break;
271
}
272
*p=*(p+1)='\0';
273
 
274
@ @=
275
octa mmix_fwrite @,@,@[ARGS((unsigned char,octa,octa))@];@+@t}\6{@>
276
octa mmix_fwrite(handle,buffer,size)
277
  unsigned char handle;
278
  octa buffer,size;
279
{
280
  char buf[256];
281
  register int n;
282
  if (!(sfile[handle].mode&0x2)) return ominus(zero_octa,size);
283
  if (sfile[handle].mode&0x8) sfile[handle].mode &=~ 0x1;
284
  while (1) {
285
    if (size.h || size.l>=256) n=mmgetchars(buf,256,buffer,-1);
286
    else n=mmgetchars(buf,size.l,buffer,-1);
287
    size=incr(size,-n);
288
    if (fwrite(buf,1,n,sfile[handle].fp)!=n) return ominus(zero_octa,size);
289
    fflush(sfile[handle].fp);
290
    if (!size.l && !size.h) return zero_octa;
291
    buffer=incr(buffer,n);
292
  }
293
}
294
 
295
@ @=
296
octa mmix_fputs @,@,@[ARGS((unsigned char,octa))@];@+@t}\6{@>
297
octa mmix_fputs(handle,string)
298
  unsigned char handle;
299
  octa string;
300
{
301
  char buf[256];
302
  register int n;
303
  octa o;
304
  o=zero_octa;
305
  if (!(sfile[handle].mode&0x2)) return neg_one;
306
  if (sfile[handle].mode&0x8) sfile[handle].mode &=~ 0x1;
307
  while (1) {
308
    n=mmgetchars(buf,256,string,0);
309
    if (fwrite(buf,1,n,sfile[handle].fp)!=n) return neg_one;
310
    o=incr(o,n);
311
    if (n<256) {
312
      fflush(sfile[handle].fp);
313
      return o;
314
    }
315
    string=incr(string,n);
316
  }
317
}
318
 
319
@ @=
320
octa mmix_fputws @,@,@[ARGS((unsigned char,octa))@];@+@t}\6{@>
321
octa mmix_fputws(handle,string)
322
  unsigned char handle;
323
  octa string;
324
{
325
  char buf[256];
326
  register int n;
327
  octa o;
328
  o=zero_octa;
329
  if (!(sfile[handle].mode&0x2)) return neg_one;
330
  if (sfile[handle].mode&0x8) sfile[handle].mode &=~ 0x1;
331
  while (1) {
332
    n=mmgetchars(buf,256,string,1);
333
    if (fwrite(buf,1,n,sfile[handle].fp)!=n) return neg_one;
334
    o=incr(o,n>>1);
335
    if (n<256) {
336
      fflush(sfile[handle].fp);
337
      return o;
338
    }
339
    string=incr(string,n);
340
  }
341
}
342
 
343
@ @d sign_bit ((unsigned)0x80000000)
344
 
345
@=
346
octa mmix_fseek @,@,@[ARGS((unsigned char,octa))@];@+@t}\6{@>
347
octa mmix_fseek(handle,offset)
348
  unsigned char handle;
349
  octa offset;
350
{
351
  if (!(sfile[handle].mode&0x4)) return neg_one;
352
  if (sfile[handle].mode&0x8) sfile[handle].mode = 0xf;
353
  if (offset.h&sign_bit) {
354
    if (offset.h!=0xffffffff || !(offset.l&sign_bit)) return neg_one;
355
    if (fseek(sfile[handle].fp,(int)offset.l+1,SEEK_END)!=0) return neg_one;
356
  }@+else {
357
    if (offset.h || (offset.l&sign_bit)) return neg_one;
358
    if (fseek(sfile[handle].fp,(int)offset.l,SEEK_SET)!=0) return neg_one;
359
  }
360
  return zero_octa;
361
}
362
 
363
@ @=
364
octa mmix_ftell @,@,@[ARGS((unsigned char))@];@+@t}\6{@>
365
octa mmix_ftell(handle)
366
  unsigned char handle;
367
{
368
  register long x;
369
  octa o;
370
  if (!(sfile[handle].mode&0x4)) return neg_one;
371
  x=ftell(sfile[handle].fp);
372
  if (x<0) return neg_one;
373
  o.h=0, o.l=x;
374
  return o;
375
}
376
 
377
@ One last subroutine belongs here, just in case the user has
378
modified the standard error handle.
379
 
380
@=
381
void print_trip_warning @,@,@[ARGS((int,octa))@];@+@t}\6{@>
382
void print_trip_warning(n,loc)
383
  int n;
384
  octa loc;
385
{
386
  if (sfile[2].mode&0x2)
387
    fprintf(sfile[2].fp,"Warning: %s at location %08x%08x\n",
388
             trip_warning[n],loc.h,loc.l);
389
}
390
 
391
@ @=
392
char *trip_warning[]={
393
"TRIP",
394
"integer divide check",
395
"integer overflow",
396
"float-to-fix overflow",
397
"invalid floating point operation",
398
"floating point overflow",
399
"floating point underflow",
400
"floating point division by zero",
401
"floating point inexact"};
402
 
403
@* Index.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.