fixed sign-extend bug
[fleet.git] / src / edu / berkeley / fleet / ies44 / InstructionEncoder.java
1 package edu.berkeley.fleet.ies44;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.*;
4 import java.io.*;
5
6 public abstract class InstructionEncoder {
7
8     /** get the bits describing this box's location on the DESTINATION HORN */
9     public abstract long getBoxAddr(BenkoBox box);
10
11     /** get the bits describing this box's location on the INSTRUCTION HORN */
12     public abstract long getBoxInstAddr(BenkoBox box);
13
14     /** given a DESTINATION HORN address, retrieve the corresponding BenkoBox object */
15     public abstract BenkoBox getBoxByAddr(long dest);
16
17     /** given an INSTRUCTION HORN address, retrieve the corresponding BenkoBox object */
18     public abstract BenkoBox getBoxByInstAddr(long dest);
19
20     /** read a machine-formatted instruction from a file (into a Java object) */
21     public Instruction readInstruction(DataInputStream is) throws IOException {
22         long inst = 0;
23         try {
24             inst = (inst << 8) | (is.readByte() & 0xff);
25             inst = (inst << 8) | (is.readByte() & 0xff);
26             inst = (inst << 8) | (is.readByte() & 0xff);
27             inst = (inst << 8) | (is.readByte() & 0xff);
28             inst = (inst << 8) | (is.readByte() & 0xff);
29             inst = (inst << 8) | (is.readByte() & 0xff);
30             return readInstruction(inst);
31         } catch (EOFException eof) {
32             return null;
33         }
34     }
35
36     public Instruction readInstruction(long instr) {
37         long inst = instr;
38         long head = inst & (0x3L << (24+11));
39         head = head >> (24+11);
40         switch((int)head) {
41             case 0: {
42                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
43                 BenkoBox dest = getBoxByAddr    ((inst >>  1) & 0x7ff);
44                 int count        = ((int)(instr >> 12)) & 0x7f;
45                 boolean tokenIn  = (instr & (1L << (11+1+7+0))) != 0;
46                 boolean dataIn   = ( instr & (1L << (11+1+7+1))) != 0;
47                 boolean latch    = (  instr & (1L << (11+1+7+2))) != 0;
48                 boolean dataOut  = (instr & (1L << (11+1+7+3))) != 0;
49                 boolean tokenOut = (instr & (1L << (11+1+7+4))) != 0;
50                 boolean recycle  = (instr & (1L)) != 0;
51                 if (latch & !dataIn) return new Instruction.Kill(name, count, tokenIn);
52                 return new Instruction.Executable(name, dest, count, tokenIn, dataIn,
53                                                   latch, dataOut, tokenOut, recycle);
54             }
55
56             case 1: {
57                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
58                 int offset = ((int)(instr >> 6)) & ~(0xffffffff << 18);
59                 if ((offset & (1<<17)) != 0) offset |= (0xffffffff << 18);
60                 int size   = ((int)(instr     )) & ~(0xffffffff << 6);
61                 return new Instruction.Literal.CodeBagDescriptor(name, offset, size);
62             }
63
64             case 2: {
65                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
66                 int val   = ((int)(instr     )) & ~(0xffffffff << 24);
67                 val = signExtend24(val);
68                 return new Instruction.Literal.Absolute(name, val);
69             }
70
71             case 3: {
72                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
73                 int val   = ((int)(instr     )) & ~(0xffffffff << 24);
74                 return new Instruction.Literal.Relative(name, val);
75             }
76
77         }
78         return null;
79
80     }
81
82     public long writeInstruction(Instruction d) {
83         long instr = 0;
84
85         // Kill is encoded as Execute with the illegal combination (Latch & ~DataIn)
86         if (d instanceof Instruction.Kill) {
87             Instruction.Kill k = (Instruction.Kill)d;
88             d = new Instruction.Executable(k.benkoBox, null, k.count, k.killOnlyStandingInstructions,
89                                            false, true, false, false, false);
90         }
91
92         if (d instanceof Instruction.Executable) {
93             Instruction.Executable inst = (Instruction.Executable)d;
94             BenkoBox dest = inst.dest;
95             instr = dest==null ? 0 : (getBoxAddr(dest) << 1);
96             if (inst.count >= (1<<8))
97                 throw new RuntimeException("count field must be less than 128");
98             instr |= (((long)inst.count) << (11+1));
99             if (inst.tokenIn)  instr |= (1L << (11+1+7+0));
100             if (inst.dataIn)   instr |= (1L << (11+1+7+1));
101             if (inst.latch)    instr |= (1L << (11+1+7+2));
102             if (inst.dataOut)  instr |= (1L << (11+1+7+3));
103             if (inst.tokenOut) instr |= (1L << (11+1+7+4));
104             if (inst.recycle)  instr |= (1L);
105             instr |= (getBoxInstAddr(inst.benkoBox) << (11+5+7+1));
106
107         } else if (d instanceof Instruction.Literal.CodeBagDescriptor) {
108             Instruction.Literal.CodeBagDescriptor lc = (Instruction.Literal.CodeBagDescriptor)d;
109             instr = (1L << (11+24));
110             if (lc.dest != null)
111                 instr |= (getBoxAddr(lc.dest)) << 24;
112             if (lc.size >= (1<<6))
113                 throw new RuntimeException("codebag sizes must be less than 2^6");
114             if (lc.offset >= (1<<17) || lc.offset <= (-1 * (1<<17)))
115                 throw new RuntimeException("codebag offsets must be in the range -(2^17)..2^17");
116             int off = (int)lc.offset;
117             off &= ~(0xffffffff << 18);
118             instr |= (off << 6);
119             instr |= (((long)lc.size));
120
121         } else if (d instanceof Instruction.Literal.Absolute) {
122             Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
123             instr = (2L << (11+24));
124             instr |= (getBoxAddr(ld.dest)) << 24;
125             if (ld.value >= (1<<25))
126                 throw new RuntimeException("literals must be less than 2^24");
127             instr |= ((long)ld.value) & ~(0xffffffff << 24);
128
129         } else if (d instanceof Instruction.Literal.Relative) {
130             Instruction.Literal.Relative lr = (Instruction.Literal.Relative)d;
131             instr = (3L << (11+24));
132             instr |= (getBoxAddr(lr.dest)) << 24;
133             if (lr.offset >= (1<<25))
134                 throw new RuntimeException("literals must be less than 2^24");
135             instr |= ((long)lr.offset);
136             
137         }
138         return instr;
139     }
140
141     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
142         long instr = writeInstruction(d);
143         os.write((int)((instr >> (5*8)) & 0xff));
144         os.write((int)((instr >> (4*8)) & 0xff));
145         os.write((int)((instr >> (3*8)) & 0xff));
146         os.write((int)((instr >> (2*8)) & 0xff));
147         os.write((int)((instr >> (1*8)) & 0xff));
148         os.write((int)((instr >> (0*8)) & 0xff));
149    }
150
151     public static int signExtend24(int val) {
152         if ((val & (1 << 23)) != 0)
153             val = val | (0xffffffff << 24);
154         return val;
155     }
156
157 }