1
2
3
4 package org.xwt.mips;
5
6 import java.io.*;
7
8 public class Interpreter extends Runtime {
9
10 private int[] registers = new int[32];
11 private intinthilo
12
13
14 private int[] fpregs = new int[32];
15
16
17
18
19
20
21
22 private int fcsr;
23
24 private int nextPC;
25
26
27 private final void setFC(boolean b) { fcsr = (fcsr&~0x800000) | (b ? 0x800000 : 0x000000); }
28 private final int roundingMode() { return fcsr & 3; }
29 private final double getDouble(int r) {
30 return Double.longBitsToDouble(((fpregs[r+1]&0xffffffffL) << 32) | (fpregs[r]&0xffffffffL));
31 }
32 private final void setDouble(int r, double d) {
33 long l = Double.doubleToLongBits(d);
34 fpregs[r+1] = (int)(l >>> 32); fpregs[r] = (int)l;
35 }
36 private final float getFloat(int r) { return Float.intBitsToFloat(fpregs[r]); }
37 private final void setFloat(int r, float f) { fpregs[r] = Float.floatToRawIntBits(f); }
38
39 protected void _execute() throws ExecutionException { runSome(); }
40
41
42
43 private final int runSome() throws FaultException,ExecutionException {
44 int[] r = registers;
45 int[] f = fpregs;
46 int pc = nextPC;
47 int nextPC = pc + 4;
48 try {
49 OUTER: for(;;) {
50 int insn;
51 try {
52 insn = readPages[pc>>>PAGE_SHIFT][(pc>>>2)&PAGE_WORDS-1];
53 } catch (RuntimeException e) {
54 insn = memRead(pc);
55 }
56
57 int op = (insn >>> 26) & 0xff;
58 int rs = (insn >>> 21) & 0x1f;
59 int rt = (insn >>> 16) & 0x1f;
60 int ft = (insn >>> 16) & 0x1f;
61 int rd = (insn >>> 11) & 0x1f;
62 int fs = (insn >>> 11) & 0x1f;
63 int shamt = (insn >>> 6) & 0x1f;
64 int fd = (insn >>> 6) & 0x1f;
65 int subcode = insn & 0x3f;
66
67 int jumpTarget = (insn & 0x03ffffff);
68 int unsignedImmediate = insn & 0xffff;
69 int signedImmediate = (insn << 16) >> 16;
70 int branchTarget = signedImmediate;
71
72 intintp, addr;
73
74 r[ZERO] = 0;
75
76 switch(op) {
77 case 0: {
78 switch(subcode) {
79 case 0:
80 if(insn == 0) break;
81 r[rd] = r[rt] << shamt;
82 break;
83 case 2:
84 r[rd] = r[rt] >>> shamt;
85 break;
86 case 3:
87 r[rd] = r[rt] >> shamt;
88 break;
89 case 4:
90 r[rd] = r[rt] << (r[rs]&0x1f);
91 break;
92 case 6:
93 r[rd] = r[rt] >>> (r[rs]&0x1f);
94 break;
95 case 7:
96 r[rd] = r[rt] >> (r[rs]&0x1f);
97 break;
98 case 8:
99 tmp = r[rs]; pc += 4; nextPC = tmp;
100 continue OUTER;
101 case 9:
102 tmp = r[rs]; pc += 4; r[rd] = pc+4; nextPC = tmp;
103 continue OUTER;
104 case 12:
105 r[V0] = syscall(r[V0],r[A0],r[A1],r[A2],r[A3]);
106 if(state != RUNNING) {
107 this.nextPC = nextPC;
108 break OUTER;
109 }
110 break;
111 case 13:
112 throw new ExecutionException("Break");
113 case 16:
114 r[rd] = hi;
115 break;
116 case 17:
117 hi = r[rs];
118 break;
119 case 18:
120 r[rd] = lo;
121 break;
122 case 19:
123 lo = r[rs];
124 break;
125 case 24: {
126 long hilo = (long)(r[rs]) * ((long)r[rt]);
127 hi = (int) (hilo >>> 32);
128 lo = (int) hilo;
129 break;
130 }
131 case 25: {
132 long hilo = (r[rs] & 0xffffffffL) * (r[rt] & 0xffffffffL);
133 hi = (int) (hilo >>> 32);
134 lo = (int) hilo;
135 break;
136 }
137 case 26:
138 hi = r[rs]%r[rt];
139 lo = r[rs]/r[rt];
140 break;
141 case 27:
142 hi = (int)((r[rs] & 0xffffffffL) % (r[rt] & 0xffffffffL));
143 lo = (int)((r[rs] & 0xffffffffL) / (r[rt] & 0xffffffffL));
144 break;
145 case 32:
146 throw new ExecutionException("ADD (add with oveflow trap) not suported");
147
150 case 33:
151 r[rd] = r[rs] + r[rt];
152 break;
153 case 34:
154 throw new ExecutionException("SUB (sub with oveflow trap) not suported");
155
158 case 35:
159 r[rd] = r[rs] - r[rt];
160 break;
161 case 36:
162 r[rd] = r[rs] & r[rt];
163 break;
164 case 37:
165 r[rd] = r[rs] | r[rt];
166 break;
167 case 38:
168 r[rd] = r[rs] ^ r[rt];
169 break;
170 case 39:
171 r[rd] = ~(r[rs] | r[rt]);
172 break;
173 case 42:
174 r[rd] = r[rs] < r[rt] ? 1 : 0;
175 break;
176 case 43:
177 r[rd] = ((r[rs] & 0xffffffffL) < (r[rt] & 0xffffffffL)) ? 1 : 0;
178 break;
179 default:
180 throw new ExecutionException("Illegal instruction 0/" + subcode);
181 }
182 break;
183 }
184 case 1: {
185 switch(rt) {
186 case 0:
187 if(r[rs] < 0) {
188 pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
189 continue OUTER;
190 }
191 break;
192 case 1:
193 if(r[rs] >= 0) {
194 pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
195 continue OUTER;
196 }
197 break;
198 case 16:
199 if(r[rs] < 0) {
200 pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp;
201 continue OUTER;
202 }
203 break;
204 case 17:
205 if(r[rs] >= 0) {
206 pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp;
207 continue OUTER;
208 }
209 break;
210 default:
211 throw new ExecutionException("Illegal Instruction");
212 }
213 break;
214 }
215 case 2: {
216 tmp = (pc&0xf0000000) | (jumpTarget << 2);
217 pc+=4; nextPC = tmp;
218 continue OUTER;
219 }
220 case 3: {
221 tmp = (pc&0xf0000000) | (jumpTarget << 2);
222 pc+=4; r[RA] = pc+4; nextPC = tmp;
223 continue OUTER;
224 }
225 case 4:
226 if(r[rs] == r[rt]) {
227 pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
228 continue OUTER;
229 }
230 break;
231 case 5:
232 if(r[rs] != r[rt]) {
233 pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
234 continue OUTER;
235 }
236 break;
237 case 6:
238 if(r[rs] <= 0) {
239 pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
240 continue OUTER;
241 }
242 break;
243 case 7:
244 if(r[rs] > 0) {
245 pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
246 continue OUTER;
247 }
248 break;
249 case 8:
250 r[rt] = r[rs] + signedImmediate;
251 break;
252 case 9:
253 r[rt] = r[rs] + signedImmediate;
254 break;
255 case 10:
256 r[rt] = r[rs] < signedImmediate ? 1 : 0;
257 break;
258 case 11:
259 r[rt] = (r[rs]&0xffffffffL) < (unsignedImmediate&0xffffffffL) ? 1 : 0;
260 break;
261 case 12:
262 r[rt] = r[rs] & unsignedImmediate;
263 break;
264 case 13:
265 r[rt] = r[rs] | unsignedImmediate;
266 break;
267 case 14:
268 r[rt] = r[rs] ^ unsignedImmediate;
269 break;
270 case 15:
271 r[rt] = unsignedImmediate << 16;
272 break;
273 case 16:
274 throw new ExecutionException("TLB/Exception support not implemented");
275 case 17: {
276 boolean debug = false;
277 String line = "";
278 boolean debugon = debug && (line.indexOf("dtoa.c:51") >= 0 || line.indexOf("dtoa.c:52") >= 0 || line.indexOf("test.c") >= 0);
279 if(rs > 8 && debugon)
280 System.out.println(" FP Op: " + op + "/" + rs + "/" + subcode + " " + line);
281
282 if(roundingMode() != 0 && rs != 6 && !((rs==16 || rs==17) && subcode == 36 ))
283 throw new ExecutionException("Non-cvt.w.z operation attempted with roundingMode != round to nearest");
284 switch(rs) {
285 case 0:
286 r[rt] = f[rd];
287 break;
288 case 2:
289 if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable");
290 r[rt] = fcsr;
291 break;
292 case 4:
293 f[rd] = r[rt];
294 break;
295 case 6:
296 if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable");
297 fcsr = r[rt];
298 break;
299 case 8:
300 if(((fcsr&0x800000)!=0) == (((insn>>>16)&1)!=0)) {
301 pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
302 continue OUTER;
303 }
304 break;
305 case 16: {
306 switch(subcode) {
307 case 0:
308 setFloat(fd,getFloat(fs)+getFloat(ft));
309 break;
310 case 1:
311 setFloat(fd,getFloat(fs)-getFloat(ft));
312 break;
313 case 2:
314 setFloat(fd,getFloat(fs)*getFloat(ft));
315 break;
316 case 3:
317 setFloat(fd,getFloat(fs)/getFloat(ft));
318 break;
319 case 5:
320 setFloat(fd,Math.abs(getFloat(fs)));
321 break;
322 case 6:
323 f[fd] = f[fs];
324 break;
325 case 7:
326 setFloat(fd,-getFloat(fs));
327 break;
328 case 33:
329 setDouble(fd,getFloat(fs));
330 break;
331 case 36:
332 switch(roundingMode()) {
333 case 0: f[fd] = (int)Math.floor(getFloat(fs)+0.5f); break;
334 case 1: f[fd] = (int)getFloat(fs); break;
335 case 2: f[fd] = (int)Math.ceil(getFloat(fs)); break;
336 case 3: f[fd] = (int)Math.floor(getFloat(fs)); break;
337 }
338 break;
339 case -50:
340 setFC(getFloat(fs) == getFloat(ft));
341 break;
342 case 60:
343 setFC(getFloat(fs) < getFloat(ft));
344 break;
345 default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode);
346 }
347 break;
348 }
349 case 17: {
350 switch(subcode) {
351 case 0:
352 setDouble(fd,getDouble(fs)+getDouble(ft));
353 break;
354 case 1:
355 if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") - f" + ft + " (" + getDouble(ft) + ")");
356 setDouble(fd,getDouble(fs)-getDouble(ft));
357 break;
358 case 2:
359 if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") * f" + ft + " (" + getDouble(ft) + ")");
360 setDouble(fd,getDouble(fs)*getDouble(ft));
361 if(debugon) System.out.println("f" + fd + " = " + getDouble(fd));
362 break;
363 case 3:
364 setDouble(fd,getDouble(fs)/getDouble(ft));
365 break;
366 case 5:
367 setDouble(fd,Math.abs(getDouble(fs)));
368 break;
369 case 6:
370 f[fd] = f[fs];
371 f[fd+1] = f[fs+1];
372 break;
373 case 7:
374 setDouble(fd,-getDouble(fs));
375 break;
376 case 32:
377 setFloat(fd,(float)getDouble(fs));
378 break;
379 case 36:
380 if(debugon) System.out.println("CVT.W.D rm: " + roundingMode() + " f" + fs + ":" + getDouble(fs));
381 switch(roundingMode()) {
382 case 0: f[fd] = (int)Math.floor(getDouble(fs)+0.5); break;
383 case 1: f[fd] = (int)getDouble(fs); break;
384 case 2: f[fd] = (int)Math.ceil(getDouble(fs)); break;
385 case 3: f[fd] = (int)Math.floor(getDouble(fs)); break;
386 }
387 if(debugon) System.out.println("CVT.W.D: f" + fd + ":" + f[fd]);
388 break;
389 case 50:
390 setFC(getDouble(fs) == getDouble(ft));
391 break;
392 case 60:
393 setFC(getDouble(fs) < getDouble(ft));
394 break;
395 case 62:
396 setFC(getDouble(fs) <= getDouble(ft));
397 break;
398 default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode);
399 }
400 break;
401 }
402 case 20: {
403 switch(subcode) {
404 case 33:
405 setDouble(fd,(double)f[fs]);
406 break;
407 default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode);
408 }
409 break;
410 }
411 default:
412 throw new ExecutionException("Invalid Instruction 17/" + rs);
413 }
414 break;
415 }
416 case 18: case 19:
417 throw new ExecutionException("No coprocessor installed");
418 case 32: {
419 addr = r[rs] + signedImmediate;
420 try {
421 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
422 } catch(RuntimeException e) {
423 tmp = memRead(addr&~3);
424 }
425 switch(addr&3) {
426 case 0: tmp = (tmp>>>24)&0xff; break;
427 case 1: tmp = (tmp>>>16)&0xff; break;
428 case 2: tmp = (tmp>>> 8)&0xff; break;
429 case 3: tmp = (tmp>>> 0)&0xff; break;
430 }
431 if((tmp&0x80)!=0) tmp |= 0xffffff00;
432 r[rt] = tmp;
433 break;
434 }
435 case 33: {
436 addr = r[rs] + signedImmediate;
437 try {
438 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
439 } catch(RuntimeException e) {
440 tmp = memRead(addr&~3);
441 }
442 switch(addr&2) {
443 case 0: tmp = (tmp>>>16)&0xffff; break;
444 case 2: tmp = (tmp>>> 0)&0xffff; break;
445 }
446 if((tmp&0x8000)!=0) tmp |= 0xffff0000;
447 r[rt] = tmp;
448 break;
449 }
450 case 34: {
451 addr = r[rs] + signedImmediate;
452 try {
453 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
454 } catch(RuntimeException e) {
455 tmp = memRead(addr&~3);
456 }
457 switch(addr&3) {
458 case 0: r[rt] = (r[rt]&0x00000000)|(tmp<< 0); break;
459 case 1: r[rt] = (r[rt]&0x000000ff)|(tmp<< 8); break;
460 case 2: r[rt] = (r[rt]&0x0000ffff)|(tmp<<16); break;
461 case 3: r[rt] = (r[rt]&0x00ffffff)|(tmp<<24); break;
462 }
463 break;
464 }
465 case 35:
466 addr = r[rs] + signedImmediate;
467 try {
468 r[rt] = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
469 } catch(RuntimeException e) {
470 r[rt] = memRead(addr);
471 }
472 break;
473 case 36: {
474 addr = r[rs] + signedImmediate;
475 try {
476 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
477 } catch(RuntimeException e) {
478 tmp = memRead(addr);
479 }
480 switch(addr&3) {
481 case 0: r[rt] = (tmp>>>24)&0xff; break;
482 case 1: r[rt] = (tmp>>>16)&0xff; break;
483 case 2: r[rt] = (tmp>>> 8)&0xff; break;
484 case 3: r[rt] = (tmp>>> 0)&0xff; break;
485 }
486 break;
487 }
488 case 37: {
489 addr = r[rs] + signedImmediate;
490 try {
491 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
492 } catch(RuntimeException e) {
493 tmp = memRead(addr&~3);
494 }
495 switch(addr&2) {
496 case 0: r[rt] = (tmp>>>16)&0xffff; break;
497 case 2: r[rt] = (tmp>>> 0)&0xffff; break;
498 }
499 break;
500 }
501 case 38: {
502 addr = r[rs] + signedImmediate;
503 try {
504 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
505 } catch(RuntimeException e) {
506 tmp = memRead(addr&~3);
507 }
508 switch(addr&3) {
509 case 0: r[rt] = (r[rt]&0xffffff00)|(tmp>>>24); break;
510 case 1: r[rt] = (r[rt]&0xffff0000)|(tmp>>>16); break;
511 case 2: r[rt] = (r[rt]&0xff000000)|(tmp>>> 8); break;
512 case 3: r[rt] = (r[rt]&0x00000000)|(tmp>>> 0); break;
513 }
514 break;
515 }
516 case 40: {
517 addr = r[rs] + signedImmediate;
518 try {
519 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
520 } catch(RuntimeException e) {
521 tmp = memRead(addr&~3);
522 }
523 switch(addr&3) {
524 case 0: tmp = (tmp&0x00ffffff) | ((r[rt]&0xff)<<24); break;
525 case 1: tmp = (tmp&0xff00ffff) | ((r[rt]&0xff)<<16); break;
526 case 2: tmp = (tmp&0xffff00ff) | ((r[rt]&0xff)<< 8); break;
527 case 3: tmp = (tmp&0xffffff00) | ((r[rt]&0xff)<< 0); break;
528 }
529 try {
530 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
531 } catch(RuntimeException e) {
532 memWrite(addr&~3,tmp);
533 }
534 break;
535 }
536 case 41: {
537 addr = r[rs] + signedImmediate;
538 try {
539 tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
540 } catch(RuntimeException e) {
541 tmp = memRead(addr&~3);
542 }
543 switch(addr&2) {
544 case 0: tmp = (tmp&0x0000ffff) | ((r[rt]&0xffff)<<16); break;
545 case 2: tmp = (tmp&0xffff0000) | ((r[rt]&0xffff)<< 0); break;
546 }
547 try {
548 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
549 } catch(RuntimeException e) {
550 memWrite(addr&~3,tmp);
551 }
552 break;
553 }
554 case 42: {
555 addr = r[rs] + signedImmediate;
556 tmp = memRead(addr&~3);
557 switch(addr&3) {
558 case 0: tmp=(tmp&0x00000000)|(r[rt]>>> 0); break;
559 case 1: tmp=(tmp&0xff000000)|(r[rt]>>> 8); break;
560 case 2: tmp=(tmp&0xffff0000)|(r[rt]>>>16); break;
561 case 3: tmp=(tmp&0xffffff00)|(r[rt]>>>24); break;
562 }
563 try {
564 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
565 } catch(RuntimeException e) {
566 memWrite(addr&~3,tmp);
567 }
568 break;
569 }
570 case 43:
571 addr = r[rs] + signedImmediate;
572 try {
573 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = r[rt];
574 } catch(RuntimeException e) {
575 memWrite(addr&~3,r[rt]);
576 }
577 break;
578 case 46: {
579 addr = r[rs] + signedImmediate;
580 tmp = memRead(addr&~3);
581 switch(addr&3) {
582 case 0: tmp=(tmp&0x00ffffff)|(r[rt]<<24); break;
583 case 1: tmp=(tmp&0x0000ffff)|(r[rt]<<16); break;
584 case 2: tmp=(tmp&0x000000ff)|(r[rt]<< 8); break;
585 case 3: tmp=(tmp&0x00000000)|(r[rt]<< 0); break;
586 }
587 memWrite(addr&~3,tmp);
588 break;
589 }
590 case 49:
591 f[rt] = memRead(r[rs] + signedImmediate);
592 break;
593 case 57:
594 memWrite(r[rs] + signedImmediate,f[rt]);
595 break;
596 default:
597 throw new ExecutionException("Invalid Instruction: " + op);
598 }
599 pc = nextPC;
600 nextPC = pc + 4;
601 }
602 } catch(ExecutionException e) {
603 this.nextPC = pc;
604 throw e;
605 }
606 return 0;
607 }
608
609
610 void loadImage(Object file) throws IOException {
611 ELF elf = new ELF(file);
612 if(elf.header.type != ELF.ELFHeader.ET_EXEC)
613 throw new IOException("Binary is not an executable");
614 if(elf.header.machine != ELF.ELFHeader.EM_MIPS)
615 throw new IOException("Binary is not for the MIPS I Architecture");
616 entryPoint = elf.header.entry;
617 ELF.PHeader[] pheaders = elf.pheaders;
618 brk = 0;
619 for(int i=0;i<pheaders.length;i++) {
620 ELF.PHeader ph = pheaders[i];
621 if(ph.type != ELF.PHeader.PT_LOAD) continue;
622 int memsize = ph.memsz;
623 int filesize = ph.filesz;
624 if(memsize == 0) continue;
625 if(memsize < 0) throw new IOException("pheader size too large");
626 int addr = ph.vaddr;
627 if(addr == 0x0) throw new IOException("pheader vaddr == 0x0");
628 if(addr+memsize >= (brk<<PAGE_SHIFT)) brk = (addr+memsize+PAGE_SIZE-1) >> PAGE_SHIFT;
629
630 for(int j=0;j<memsize+PAGE_SIZE-1;j+=PAGE_SIZE) {
631 int page = (j+addr) >>> PAGE_SHIFT;
632 if(readPages[page] == null)
633 readPages[page] = new int[PAGE_WORDS];
634 if(ph.writable()) writePages[page] = readPages[page];
635 }
636 if(filesize != 0) {
637 filesize = filesize & ~3;
638 DataInputStream dis = new DataInputStream(ph.getInputStream());
639 do {
640 readPages[addr >>> PAGE_SHIFT][(addr >>> 2)&(PAGE_WORDS-1)] = dis.readInt();
641 addr+=4;
642 filesize-=4;
643 } while(filesize > 0);
644 dis.close();
645 }
646 }
647 state = INITIALIZED;
648 }
649
650 protected void _start(int pc) {
651 registers[K0] = STUFF_BASE;
652 registers[K1] = PAGE_SIZE;
653 registers[SP] = INITIAL_SP;
654 registers[RA] = 0xdeadbeef;
655 nextPC = pc;
656 }
657 public Interpreter() { super(true); }
658 public Interpreter(String filename) throws IOException { loadImage(filename); }
659 public Interpreter(byte[] bytes) throws IOException { loadImage(bytes); }
660
661 public class DebugShutdownHook implements Runnable {
662 public void run() {
663 int pc = nextPC;
664 if(getState() == RUNNING)
665 System.err.print("\nCPU Executing " + toHex(pc) + "\n");
666 }
667 }
668
669 public static void main(String[] argv) throws Exception {
670 String image = argv[0];
671 Interpreter emu = new Interpreter();
672 emu.loadImage(image);
673 java.lang.Runtime.getRuntime().addShutdownHook(new Thread(emu.new DebugShutdownHook()));
674
675 int addr = emu.sbrk(PAGE_SIZE);
676 for(int i=0;i<10;i++) {
677 String s = "User Info item: " + (i+1) + "\0";
678 byte[] b = s.getBytes("US-ASCII");
679 emu.copyout(b,addr,b.length);
680 emu.setUserInfo(i,addr);
681 addr += b.length;
682 }
683
684 int status = emu.run(argv);
685 System.err.println("Exit status: " + status);
686 System.exit(status);
687 }
688 }
689