1 package org.ibex.classgen;
6 /** A class representing a method in a generated classfile
7 @see ClassFile#addMethod */
8 public class MethodGen implements CGConst {
9 private final static boolean EMIT_NOPS = false;
11 private static final int NO_CODE = -1;
12 private static final int FINISHED = -2;
14 private final ClassFile owner;
15 private final ConstantPool cp;
16 private final String name;
17 private final Type ret;
18 private final Type[] args;
19 private final int flags;
20 private final ClassFile.AttrGen attrs;
21 private final ClassFile.AttrGen codeAttrs;
22 private final Hashtable exnTable = new Hashtable();
23 private final Hashtable thrownExceptions = new Hashtable();
25 private int maxStack = 16;
26 private int maxLocals;
33 public String toString() { StringBuffer sb = new StringBuffer(); toString(sb, "<init>"); return sb.toString(); }
34 public void toString(StringBuffer sb, String constructorName) {
35 sb.append(ClassFile.flagsToString(flags));
39 if (name.equals("<clinit>")) sb.append("static ");
41 if (name.equals("<init>")) sb.append(constructorName);
44 for(int i=0; i<args.length; i++)
45 sb.append((i==0?"":", ")+args[i]);
53 MethodGen(ConstantPool cp, DataInput in, ClassFile owner) throws IOException {
56 flags = in.readShort();
57 name = cp.getUtf8ByIndex(in.readShort());
58 String descriptor = cp.getUtf8ByIndex(in.readShort());
59 String ret = descriptor.substring(descriptor.indexOf(')')+1);
60 this.ret = Type.instance(ret);
61 //String args = descriptor.substring(1, descriptor.indexOf(')'));
62 args = new Type[0]; // FIXME
64 attrs = new ClassFile.AttrGen(cp, in);
67 MethodGen(ClassFile owner, String name, Type ret, Type[] args, int flags) {
68 if((flags & ~(ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT|ACC_STRICT)) != 0)
69 throw new IllegalArgumentException("invalid flags");
77 attrs = new ClassFile.AttrGen(cp);
78 codeAttrs = new ClassFile.AttrGen(cp);
81 cp.addUtf8(owner.getType().method(name, ret, args).getDescriptor());
83 if((owner.flags & ACC_INTERFACE) != 0 || (flags & (ACC_ABSTRACT|ACC_NATIVE)) != 0) size = capacity = -1;
85 maxLocals = Math.max(args.length + (flags&ACC_STATIC)==0 ? 1 : 0, 4);
88 private class ExnTableEnt {
92 public ConstantPool.Ent typeEnt;
93 public ExnTableEnt(int start, int end, int handler, ConstantPool.Ent typeEnt) {
96 this.handler = handler;
97 this.typeEnt = typeEnt;
99 public void dump(DataOutput o, int[] pc, int endPC) throws IOException {
100 o.writeShort(pc[start]);
101 o.writeShort(end==pc.length ? endPC : pc[end]);
102 o.writeShort(pc[handler]);
103 o.writeShort(cp.getIndex(typeEnt));
107 /** Adds an exception handler for the range [<i>start</i>, <i>end</i>) pointing to <i>handler</i>
108 @param start The instruction to start at (inclusive)
109 @param end The instruction to end at (exclusive)
110 @param handler The instruction of the excepton handler
111 @param type The type of exception that is to be handled (MUST inherit from Throwable)
113 public final void addExceptionHandler(int start, int end, int handler, Type.Class type) {
114 exnTable.put(type, new ExnTableEnt(start, end, handler, cp.add(type)));
117 /** Adds a exception type that can be thrown from this method
118 NOTE: This isn't enforced by the JVM. This is for reference only. A method can throw exceptions not declared to be thrown
119 @param type The type of exception that can be thrown
121 public final void addThrow(Type.Class type) {
122 thrownExceptions.put(type, cp.add(type));
125 private final void grow() { if(size == capacity) grow(size+1); }
126 private final void grow(int newCap) {
127 if(capacity == NO_CODE) throw new IllegalStateException("method can't have code");
128 if(capacity == FINISHED) throw new IllegalStateException("method has been finished");
129 if(newCap <= capacity) return;
130 newCap = Math.max(newCap, capacity == 0 ? 256 : capacity*2);
132 byte[] op2 = new byte[newCap];
133 if(capacity != 0) System.arraycopy(op, 0, op2, 0, size);
136 Object[] arg2 = new Object[newCap];
137 if(capacity != 0) System.arraycopy(arg, 0, arg2, 0, size);
143 /** Returns the size (in instructions) of this method
144 @return The size of the method (in instructions)
146 public final int size() { return size; }
148 // These two are optimized for speed, they don't call set() below
149 /** Add a bytecode (with no argument) to the method */
150 public final int add(byte op) {
152 if(s == capacity) grow();
157 /** Set the bytecode at position <i>pos</i> to <i>op</i> */
158 public final void set(int pos, byte op) { this.op[pos] = op; }
160 /** Adds a bytecode, <i>op</i>, with argument <i>arg</i> to the method
161 @return The position of the new bytecode
163 public final int add(byte op, Object arg) { if(capacity == size) grow(); set(size, op, arg); return size++; }
164 /** Adds a bytecode with a boolean argument - equivalent to add(op, arg?1:0);
165 @return The position of the new bytecode
168 public final int add(byte op, boolean arg) { if(capacity == size) grow(); set(size, op, arg); return size++; }
169 /** Adds a bytecode with an integer argument. This is equivalent to add(op, new Integer(arg)), but optimized to prevent the allocation when possible
170 @return The position of the new bytecode
171 @see #add(byte, Object)
173 public final int add(byte op, int arg) { if(capacity == size) grow(); set(size, op, arg); return size++; }
175 /** Gets the bytecode at position <i>pos</i>
176 @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
178 public final byte get(int pos) { return op[pos]; }
180 /** Gets the bytecode at position <i>pos</i>. NOTE: This isn't necessarily the same object that was set with add or set.
181 Arguments for instructions which access the constant pool (LDC, INVOKEVIRTUAL, etc) are converted to a more efficient
182 interal form when they are added. The value returned from this method for these instruction can be reused, but there
183 is no way to retrieve the original object
184 @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
186 public final Object getArg(int pos) { return arg[pos]; }
188 /** Sets the argument for <i>pos</i> to <i>arg</i>. This is equivalent to set(pos, op, new Integer(arg)), but optimized to prevent the allocation when possible.
189 @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
190 @see #setArg(int, Object) */
191 public final void setArg(int pos, int arg) { set(pos, op[pos], N(arg)); }
192 /** Sets the argument for <i>pos</i> to <i>arg</i>.
193 @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
195 public final void setArg(int pos, Object arg) { set(pos, op[pos], arg); }
197 /** Sets the bytecode and argument at <i>pos</i> to <i>op</i> and <i>arg</i> respectivly.
198 This is equivalent to set(pos, op, arg?1:0)
199 @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
201 public final void set(int pos, byte op, boolean arg) { set(pos, op, arg?1:0); }
203 // This MUST handle x{LOAD, STORE} and LDC with an int arg WITHOUT falling back to set(int, byte, Object)
204 /** Sets the bytecode and argument at <i>pos</i> to <i>op</i> and <i>n</i> respectivly.
205 This is equivalent to set(pos, op, new Integer(n)), but optimized to prevent the allocation when possible.
206 @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
208 public final void set(int pos, byte op, int n) {
213 case -1: op = ICONST_M1; break OUTER;
214 case 0: op = ICONST_0; break OUTER;
215 case 1: op = ICONST_1; break OUTER;
216 case 2: op = ICONST_2; break OUTER;
217 case 3: op = ICONST_3; break OUTER;
218 case 4: op = ICONST_4; break OUTER;
219 case 5: op = ICONST_5; break OUTER;
221 if(n >= -128 && n <= 127) { op = BIPUSH; arg = N(n); }
222 else if(n >= -32768 && n <= 32767) { op = SIPUSH; arg = N(n); }
223 else { arg = cp.add(N(n)); }
225 case ILOAD: case ISTORE: case LLOAD: case LSTORE: case FLOAD:
226 case FSTORE: case DLOAD: case DSTORE: case ALOAD: case ASTORE:
227 if(n >= maxLocals) maxLocals = n + 1;
228 if(n >= 0 && n <= 3) {
231 case ILOAD: base = ILOAD_0; break;
232 case ISTORE: base = ISTORE_0; break;
233 case LLOAD: base = LLOAD_0; break;
234 case LSTORE: base = LSTORE_0; break;
235 case FLOAD: base = FLOAD_0; break;
236 case FSTORE: base = FSTORE_0; break;
237 case DLOAD: base = DLOAD_0; break;
238 case DSTORE: base = DSTORE_0; break;
239 case ALOAD: base = ALOAD_0; break;
240 case ASTORE: base = ASTORE_0; break;
242 op = (byte)((base&0xff) + n);
255 /** Sets the bytecode and argument at <i>pos</i> to <i>op</i> and <i>arg</i> respectivly.
256 @exception ArrayIndexOutOfBoundException if pos < 0 || pos >= size()
258 public final void set(int pos, byte op, Object arg) {
260 case ILOAD: case ISTORE: case LLOAD: case LSTORE: case FLOAD:
261 case FSTORE: case DLOAD: case DSTORE: case ALOAD: case ASTORE:
262 // set(int, byte, int) always handles these ops itself
263 set(pos, op, ((Integer)arg).intValue());
266 // set(int, byte, int) always handles these opts itself
267 if(arg instanceof Integer) { set(pos, op, ((Integer)arg).intValue()); return; }
268 if(arg instanceof Boolean) { set(pos, op, ((Boolean)arg).booleanValue()); return; }
270 if(arg instanceof Long) {
271 long l = ((Long)arg).longValue();
272 if(l == 0L) { this.op[pos] = LCONST_0; return; }
273 if(l == 1L) { this.op[pos] = LCONST_1; return; }
276 if(arg instanceof Long || arg instanceof Double) op = LDC2_W;
278 case INVOKEINTERFACE: {
282 int opdata = OP_DATA[op&0xff];
283 if((opdata&OP_CPENT_FLAG) != 0 && !(arg instanceof ConstantPool.Ent)) {
284 if (op==INVOKEINTERFACE) arg = cp.add(arg, true);
285 else arg = cp.add(arg);
287 else if((opdata&OP_VALID_FLAG) == 0)
288 throw new IllegalArgumentException("unknown bytecode");
293 /** This class represents the arguments to the TABLESWITH and LOOKUPSWITCH bytecodes
297 public static abstract class SI {
298 public final Object[] targets;
299 public Object defaultTarget;
301 SI(int size) { targets = new Object[size]; }
302 public void setTarget(int pos, Object val) { targets[pos] = val; }
303 public void setTarget(int pos, int val) { targets[pos] = N(val); }
304 public void setDefaultTarget(int val) { setDefaultTarget(N(val)); }
305 public void setDefaultTarget(Object o) { defaultTarget = o; }
306 public int size() { return targets.length; }
308 public int getTarget(int pos) { return ((Integer)targets[pos]).intValue(); }
309 public int getDefaultTarget() { return ((Integer)defaultTarget).intValue(); }
311 abstract int length();
314 /** This class represents the arguments to the TABLESWITCH bytecode */
315 public static class TSI extends SI {
318 public TSI(int lo, int hi) {
323 public void setTargetForVal(int val, Object o) { setTarget(val-lo, o); }
324 public void setTargetForVal(int val, int n) { setTarget(val-lo, n); }
326 int length() { return 12 + targets.length * 4; } // 4bytes/target, hi, lo, default
329 /** This class represents the arguments to the LOOKUPSWITCH bytecode */
330 public static class LSI extends SI {
331 public final int[] vals;
332 public LSI(int size) {
334 this.vals = new int[size];
336 public final void setVal(int pos, int val) { vals[pos] = val; }
338 int length() { return 8 + targets.length * 8; } // key/val per target, default, count
341 /** This class represents the arguments to byecodes that take two integer arguments. */
342 public static class Pair {
345 public Pair(int i1, int i2) { this.i1 = i1; this.i2 = i2; }
348 public static class Wide {
349 public final byte op;
350 public final int varNum;
352 Wide(byte op, int varNum) { this(op, varNum, 0); }
353 Wide(byte op, int varNum, int n) { this.op = op; this.varNum = varNum; this.n = n; }
356 /** Sets the maximum number of locals in the function to <i>maxLocals</i>. NOTE: This defaults to 0 and is automatically increased as
357 necessary when *LOAD/*STORE bytecodes are added. You do not need to call this function in most cases */
358 public void setMaxLocals(int maxLocals) { this.maxLocals = maxLocals; }
359 /** Sets the maxinum size of th stack for this function to <i>maxStack</i>. This defaults to 16< */
360 public void setMaxStack(int maxStack) { this.maxStack = maxStack; }
362 /** Computes the final bytecode for this method.
363 @exception IllegalStateException if the data for a method is in an inconsistent state (required arguments missing, etc)
364 @exception Exn if the byteocode could not be generated for any other reason (constant pool full, etc)
366 public void finish() {
369 } catch(IOException e) {
370 throw new Error("should never happen");
374 private Object resolveTarget(Object arg) {
376 if(arg instanceof PhantomTarget) {
377 target = ((PhantomTarget)arg).getTarget();
378 if(target == -1) throw new IllegalStateException("unresolved phantom target");
381 target = ((Integer)arg).intValue();
383 if(target < 0 || target >= size)
384 throw new IllegalStateException("invalid target address");
388 private void _finish() throws IOException {
389 if(size == FINISHED) return;
393 ByteArrayOutputStream baos = new ByteArrayOutputStream();
394 DataOutput o = new DataOutputStream(baos);
396 int[] pc = new int[size];
400 // Pass1 - Calculate maximum pc of each bytecode, widen some insns, resolve any unresolved jumps, etc
401 for(i=0, p=0;i<size;i++) {
402 byte op = this.op[i];
403 int opdata = OP_DATA[op&0xff];
407 if((opdata & OP_BRANCH_FLAG)!= 0) {
409 arg[i] = resolveTarget(arg[i]);
410 } catch(RuntimeException e) {
411 System.err.println("WARNING: Error resolving target for " + Integer.toHexString(op&0xff));
417 // Speical caculations
420 int arg = ((Integer)this.arg[i]).intValue();
421 if(arg < i && p - maxpc[arg] <= 32768) p += 3;
431 Object[] targets = si.targets;
432 for(j=0;j<targets.length;j++) targets[j] = resolveTarget(targets[j]);
433 si.defaultTarget = resolveTarget(si.defaultTarget);
434 p += 1 + 3 + si.length(); // opcode itself, padding, data
435 if(op == LOOKUPSWITCH) { // verify sanity of lookupswitch vals
436 int[] vals = ((LSI)si).vals;
437 for(j=1;j<vals.length;j++)
438 if(vals[j] <= vals[j-1])
439 throw new IllegalStateException("out of order/duplicate lookupswitch values");
444 case ILOAD: case ISTORE: case LLOAD: case LSTORE: case FLOAD:
445 case FSTORE: case DLOAD: case DSTORE: case ALOAD: case ASTORE:
447 int arg = ((Integer)this.arg[i]).intValue();
450 this.arg[i] = new Wide(op, arg);
455 Pair pair = (Pair) this.arg[i];
456 if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) {
458 this.arg[i] = new Wide(IINC, pair.i1, pair.i2);
463 j = cp.getIndex((ConstantPool.Ent)arg[i]);
464 if(j >= 256) this.op[i] = op = LDC_W;
468 if((j = (opdata&OP_ARG_LENGTH_MASK)) == 7) throw new Error("shouldn't be here");
472 // Pass2 - Widen instructions if they can possibly be too short
473 for(i=0;i<size;i++) {
477 int arg = ((Integer)this.arg[i]).intValue();
478 int diff = maxpc[arg] - maxpc[i];
479 if(diff < -32768 || diff > 32767)
480 op[i] = op[i] == GOTO ? GOTO_W : JSR_W;
486 // Pass3 - Calculate actual pc
487 for(i=0, p=0;i<size;i++) {
488 byte op = this.op[i];
497 p++; // opcode itself
498 p = (p + 3) & ~3; // padding
500 if(op == TABLESWITCH) p += 4 + 4 + si.size() * 4; // lo, hi, targets
501 else p += 4 + si.size() * 4 * 2; // count, key, val * targets
505 p += 2 + (((Wide)arg[i]).op == IINC ? 4 : 2);
508 int l = OP_DATA[op&0xff] & OP_ARG_LENGTH_MASK;
509 if(l == 7) throw new Error("shouldn't be here");
516 if(codeSize >= 65536) throw new ClassFile.Exn("method too large in size");
518 o.writeShort(maxStack);
519 o.writeShort(maxLocals);
520 o.writeInt(codeSize);
522 // Pass 4 - Actually write the bytecodes
523 for(i=0;i<size;i++) {
524 byte op = this.op[i];
525 int opdata = OP_DATA[op&0xff];
526 if(op == NOP && !EMIT_NOPS) continue;
528 int argLength = opdata & OP_ARG_LENGTH_MASK;
530 if(argLength == 0) continue; // skip if no args
533 Object arg = this.arg[i];
537 Pair pair = (Pair) arg;
538 if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) throw new ClassFile.Exn("overflow of iinc arg");
539 o.writeByte(pair.i1);
540 o.writeByte(pair.i2);
547 for(p = pc[i]+1;(p&3)!=0;p++) o.writeByte(0);
548 o.writeInt(pc[si.getDefaultTarget()] - mypc);
549 if(op == LOOKUPSWITCH) {
550 int[] vals = ((LSI)si).vals;
551 o.writeInt(si.size());
552 for(int j=0;j<si.size();j++) {
554 o.writeInt(pc[si.getTarget(j)] - mypc);
560 for(int j=0;j<tsi.size();j++) o.writeInt(pc[tsi.getTarget(j)] - mypc);
565 Wide wide = (Wide) arg;
566 o.writeByte(wide.op);
567 o.writeShort(wide.varNum);
568 if(wide.op == IINC) o.writeShort(wide.n);
573 if((opdata & OP_BRANCH_FLAG) != 0) {
574 int v = pc[((Integer)arg).intValue()] - pc[i];
576 if(v < -32768 || v > 32767) throw new ClassFile.Exn("overflow of s2 offset");
578 } else if(argLength == 4) {
581 throw new Error("should never happen");
583 } else if((opdata & OP_CPENT_FLAG) != 0) {
584 int v = cp.getIndex((ConstantPool.Ent)arg);
585 if(argLength == 1) o.writeByte(v);
586 else if(argLength == 2) o.writeShort(v);
587 else throw new Error("should never happen");
588 } else if(argLength == 7) {
589 throw new Error("should never happen - variable length instruction not explicitly handled");
591 int iarg = ((Integer)arg).intValue();
593 if(iarg < -128 || iarg >= 256) throw new ClassFile.Exn("overflow of s/u1 option");
595 } else if(argLength == 2) {
596 if(iarg < -32768 || iarg >= 65536) throw new ClassFile.Exn("overflow of s/u2 option");
599 throw new Error("should never happen");
606 //if(baos.size() - 8 != codeSize) throw new Error("we didn't output what we were supposed to");
608 o.writeShort(exnTable.size());
609 for(Enumeration e = exnTable.keys();e.hasMoreElements();)
610 ((ExnTableEnt)exnTable.get(e.nextElement())).dump(o, pc, codeSize);
612 o.writeShort(codeAttrs.size());
617 byte[] codeAttribute = baos.toByteArray();
618 attrs.add("Code", codeAttribute);
621 o.writeShort(thrownExceptions.size());
622 for(Enumeration e = thrownExceptions.keys();e.hasMoreElements();)
623 o.writeShort(cp.getIndex((ConstantPool.Ent)thrownExceptions.get(e.nextElement())));
624 attrs.add("Exceptions", baos.toByteArray());
626 size = capacity = FINISHED;
629 void dump(DataOutput o) throws IOException {
631 o.writeShort(cp.getUtf8Index(name));
632 o.writeShort(cp.getUtf8Index(owner.getType().method(name, ret, args).getDescriptor()));
633 o.writeShort(attrs.size());
637 /** Negates the IF* instruction, <i>op</i> (IF_ICMPGT -> IF_ICMPLE, IFNE -> IFEQ, etc)
638 @exception IllegalArgumentException if <i>op</i> isn't an IF* instruction */
639 public static byte negate(byte op) {
641 case IFEQ: return IFNE;
642 case IFNE: return IFEQ;
643 case IFLT: return IFGE;
644 case IFGE: return IFLT;
645 case IFGT: return IFLE;
646 case IFLE: return IFGT;
647 case IF_ICMPEQ: return IF_ICMPNE;
648 case IF_ICMPNE: return IF_ICMPEQ;
649 case IF_ICMPLT: return IF_ICMPGE;
650 case IF_ICMPGE: return IF_ICMPLT;
651 case IF_ICMPGT: return IF_ICMPLE;
652 case IF_ICMPLE: return IF_ICMPGT;
653 case IF_ACMPEQ: return IF_ACMPNE;
654 case IF_ACMPNE: return IF_ACMPEQ;
657 throw new IllegalArgumentException("Can't negate " + Integer.toHexString(op));
661 /** Class that represents a target that isn't currently know. The target MUST be set with setTarget() before the classfile is written.
662 This class is more or less a mutable integer */
663 public static class PhantomTarget {
664 private int target = -1;
665 public void setTarget(int target) { this.target = target; }
666 public int getTarget() { return target; }
669 private static Integer N(int n) { return new Integer(n); }
670 private static Long N(long n) { return new Long(n); }
671 private static Float N(float f) { return new Float(f); }
672 private static Double N(double d) { return new Double(d); }
673 private static int max(int a, int b) { return a > b ? a : b; }
675 private static final int OP_BRANCH_FLAG = 1<<3;
676 private static final int OP_CPENT_FLAG = 1<<4;
677 private static final int OP_VALID_FLAG = 1<<5;
678 private static final int OP_ARG_LENGTH_MASK = 7;
679 private static final boolean OP_VALID(byte op) { return (OP_DATA[op&0xff] & OP_VALID_FLAG) != 0; }
680 private static final int OP_ARG_LENGTH(byte op) { return (OP_DATA[op&0xff]&OP_ARG_LENGTH_MASK); }
681 private static final boolean OP_CPENT(byte op) { return (OP_DATA[op&0xff]&OP_CPENT_FLAG) != 0; }
682 private static final boolean OP_BRANCH(byte op) { return (OP_DATA[op&0xff]&OP_BRANCH_FLAG ) != 0; }
684 // Run perl -x src/org/ibex/classgen/CGConst.java to generate this
685 private static final byte[] OP_DATA = {
686 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
687 0x21, 0x22, 0x31, 0x32, 0x32, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
688 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
689 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
690 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
691 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
692 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
693 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
694 0x20, 0x20, 0x20, 0x20, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
695 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
696 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x21, 0x27, 0x27, 0x20, 0x20, 0x20, 0x20,
697 0x20, 0x20, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x01, 0x32, 0x21, 0x32, 0x20, 0x20,
698 0x32, 0x32, 0x20, 0x20, 0x27, 0x23, 0x2a, 0x2a, 0x2c, 0x2c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
699 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
700 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
701 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01