/* F99bTargetContext.java (c) 2010-2014 Edward Swartz All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package v9t9.tools.forthcomp.f99b; import static v9t9.machine.f99b.asm.InstF99b.*; import java.util.Stack; import v9t9.common.machine.IBaseMachine; import v9t9.machine.f99b.asm.InstF99b; import v9t9.machine.f99b.cpu.CpuF99b; import v9t9.machine.f99b.cpu.CpuStateF99b; import v9t9.machine.f99b.cpu.F99bInstructionFactory; import v9t9.tools.forthcomp.AbortException; import v9t9.tools.forthcomp.BaseGromTargetContext; import v9t9.tools.forthcomp.DictEntry; import v9t9.tools.forthcomp.F99bGromDictEntry; import v9t9.tools.forthcomp.HostContext; import v9t9.tools.forthcomp.ISemantics; import v9t9.tools.forthcomp.ITargetWord; import v9t9.tools.forthcomp.RelocEntry; import v9t9.tools.forthcomp.RelocEntry.RelocType; import v9t9.tools.forthcomp.TargetContext; import v9t9.tools.forthcomp.f99b.words.ExitI; import v9t9.tools.forthcomp.f99b.words.FieldComma; import v9t9.tools.forthcomp.words.HostLiteral; import v9t9.tools.forthcomp.words.IPrimitiveWord; import v9t9.tools.forthcomp.words.TargetColonWord; import v9t9.tools.forthcomp.words.TargetUserVariable; import v9t9.tools.forthcomp.words.TargetWord; import ejs.base.utils.HexUtils; /** * @author ejs * */ public class F99bTargetContext extends BaseGromTargetContext { private DictEntry stub4BitLit; private DictEntry stub8BitOpcode; private DictEntry stub16BitOpcode; private DictEntry stub16BitLit; private DictEntry stub16BitAddr; private DictEntry stub8BitLit; private DictEntry stubCall; private DictEntry stub16BitJump; private DictEntry stub8BitJump; private DictEntry stub4BitJump; private DictEntry stub16BitU8Lit; //private boolean localSupport; private DictEntry stub8BitNegLit; @SuppressWarnings("unused") private int startColonWord; private ITargetWord cellWord; private ITargetWord cellPlusWord; /** * @param littleEndian * @param charBits * @param cellBits * @param memorySize */ public F99bTargetContext(int memorySize) { super(false, 8, 16, memorySize); rawInstructionFactory = new F99bInstructionFactory(); stub8BitOpcode = defineStub("<<8-bit opcode>>"); stub16BitOpcode = defineStub("<<16-bit opcode>>"); stub4BitLit = defineStub("<<4-bit lit>>"); stub4BitJump = defineStub("<<4-bit jump>>"); stub8BitJump = defineStub("<<8-bit jump>>"); stub8BitLit = defineStub("<<8-bit lit>>"); stub8BitNegLit = defineStub("<<8-bit neg lit>>"); stub16BitLit = defineStub("<<16-bit lit>>"); stub16BitU8Lit = defineStub("<<16-bit U8 lit>>"); stub16BitAddr = defineStub("<<16-bit addr>>"); stub16BitJump = defineStub("<<16-bit jump>>"); stubCall = defineStub("<<call>>"); } /* (non-Javadoc) * @see v9t9.tools.forthcomp.IGromTargetContext#finishDict() */ @Override public void finishDict() { } static class TargetSQuote extends TargetWord { /** * @param entry */ public TargetSQuote(DictEntry entry) { super(entry); setCompilationSemantics(new ISemantics() { public void execute(HostContext hostContext, TargetContext targetContext) throws AbortException { //targetContext.compile(targetContext.require("((s\"))")); targetContext.buildCall(targetContext.require("((s\"))")); } }); } } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#defineBuiltins() */ @Override public void definePrims() throws AbortException { super.definePrims(); defineInlinePrim("#CELL", IlitX | 2); defineInlinePrim("cells", IlitX | 1, Ilsh); definePrim(";S", Iexit); definePrim("@", Iload); definePrim("c@", Icload); definePrim("d@", Iload_d); definePrim("!", Istore); definePrim("c!", Icstore); definePrim("d!", Istore_d); definePrim("+!", IplusStore); definePrim("c+!", IcplusStore); definePrim("d+!", IplusStore_d); definePrim("1+", I1plus); definePrim("2+", I2plus); definePrim("1-", I1minus); definePrim("2-", I2minus); definePrim("dup", Idup); definePrim("drop", Idrop); definePrim("swap", Iswap); definePrim("2swap", Iswap_d); definePrim("over", Iover); definePrim("2over", Iover_d); definePrim("rot", Irot); definePrim("2rot", Irot_d); definePrim("0=", I0equ); definePrim("D0=", I0equ_d); definePrim("=", Iequ); definePrim("D=", Iequ_d); definePrim("0branch", I0branchB); definePrim("branch", IbranchB); definePrim("negate", Ineg); definePrim("dnegate", Ineg_d); definePrim("+", Iadd); definePrim("d+", Iadd_d); definePrim("-", Isub); definePrim("d-", Isub_d); definePrim("um*", Iumul); defineInlinePrim("um/mod", Iudivmod); defineInlinePrim("nip", Iswap, Idrop); definePrim("invert", Iinv); definePrim("dinvert", Iinv_d); definePrim("not", Inot); definePrim("dnot", Inot_d); definePrim("or", Ior); definePrim("dor", Ior_d); definePrim("and", Iand); definePrim("dand", Iand_d); definePrim("xor", Ixor); definePrim("dxor", Ixor_d); definePrim("nand", Inand); definePrim("dnand", Inand_d); definePrim(">r", ItoR); definePrim("2>r", ItoR_d); definePrim("r>", IRfrom); definePrim("2r>", IRfrom_d); definePrim("rdrop", Irdrop); definePrim("r@", IatR); definePrim("i", IatR); definePrim("2r@", IatR_d); defineInlinePrim("i'", Irpidx, 1); defineInlinePrim("j", Irpidx, 2); defineInlinePrim("j'", Irpidx, 3); defineInlinePrim("k", Irpidx, 4); defineInlinePrim("k'", Irpidx, 5); defineInlinePrim("sp@", IcontextFrom, CTX_SP); defineInlinePrim("sp!", ItoContext, CTX_SP); defineInlinePrim("rp@", IcontextFrom, CTX_RP); defineInlinePrim("rp!", ItoContext, CTX_RP); defineInlinePrim("lp@", IcontextFrom, CTX_LP); defineInlinePrim("lp!", ItoContext, CTX_LP); definePrim("(do)", ItoR_d); defineInlinePrim("(loop)", IloopUp); defineInlinePrim("(+loop)", IplusLoopUp); // defineInlinePrim("(uloop)", IuloopUp); // defineInlinePrim("(u+loop)", IuplusLoopUp); defineInlinePrim("(?do)", Idup_d, ItoR_d, Isub, I0branchB); definePrim("execute", Iexecute); definePrim("?dup", Iqdup); definePrim("2dup", Idup_d); //definePrim("(context>)", IcontextFrom); //definePrim("(>context)", ItoContext); //definePrim("(user)", Iuser); defineInlinePrim("0<", IlitX, Icmp+CMP_LT); defineInlinePrim("0<=", IlitX, Icmp+CMP_LE); defineInlinePrim("0>", IlitX, Icmp+CMP_GT); defineInlinePrim("0>=", IlitX, Icmp+CMP_GE); defineInlinePrim("0U<", IlitX, Icmp+CMP_ULT); defineInlinePrim("0U<=", IlitX, Icmp+CMP_ULE); defineInlinePrim("0U>", IlitX, Icmp+CMP_UGT); defineInlinePrim("0U>=", IlitX, Icmp+CMP_UGE); defineInlinePrim("<", Icmp+CMP_LT); defineInlinePrim("<=", Icmp+CMP_LE); defineInlinePrim(">", Icmp+CMP_GT); defineInlinePrim(">=", Icmp+CMP_GE); defineInlinePrim("U<", Icmp+CMP_ULT); defineInlinePrim("U<=", Icmp+CMP_ULE); defineInlinePrim("U>", Icmp+CMP_UGT); defineInlinePrim("U>=", Icmp+CMP_UGE); defineInlinePrim("D0<", IlitX_d, Icmp+CMP_LT); defineInlinePrim("D0<=", IlitX_d, Icmp+CMP_LE); defineInlinePrim("D0>", IlitX_d, Icmp+CMP_GT); defineInlinePrim("D0>=", IlitX_d, Icmp+CMP_GE); defineInlinePrim("DU0<", IlitX_d, Icmp+CMP_ULT); defineInlinePrim("DU0<=", IlitX_d, Icmp+CMP_ULE); defineInlinePrim("DU0>", IlitX_d, Icmp+CMP_UGT); defineInlinePrim("DU0>=", IlitX_d, Icmp+CMP_UGE); defineInlinePrim("D<", Icmp_d+CMP_LT); defineInlinePrim("D<=", Icmp_d+CMP_LE); defineInlinePrim("D>", Icmp_d+CMP_GT); defineInlinePrim("D>=", Icmp_d+CMP_GE); defineInlinePrim("DU<", Icmp_d+CMP_ULT); defineInlinePrim("DU<=", Icmp_d+CMP_ULE); defineInlinePrim("DU>", Icmp_d+CMP_UGT); defineInlinePrim("DU>=", Icmp_d+CMP_UGE); defineInlinePrim("unloop", Irdrop_d); //defineInlinePrim("(unloop)", IRfrom, Irdrop_d, ItoR); defineInlinePrim("2rdrop", Irdrop_d); defineInlinePrim("2/", I2div); defineInlinePrim("2*", I2times); defineInlinePrim("LSHIFT", Ilsh); defineInlinePrim("RSHIFT", Iash); defineInlinePrim("URSHIFT", Irsh); defineInlinePrim("CRSHIFT", Icsh); defineInlinePrim("SWPB", IlitX | 8, Icsh); defineInlinePrim("DLSHIFT", Ilsh_d); defineInlinePrim("DRSHIFT", Iash_d); defineInlinePrim("DURSHIFT", Irsh_d); defineInlinePrim("DCRSHIFT", Icsh_d); defineInlinePrim("*", Iumul, Idrop); defineInlinePrim("2drop", Idrop_d); defineInlinePrim("d>q", Idup, IlitX, Icmp + CMP_LT, Idup); defineInlinePrim("dum/mod", Iudivmod_d); defineInlinePrim("s>d", Idup, IlitX, Icmp+CMP_LT); //defineInlinePrim("DOVAR", IcontextFrom, CTX_PC, I2plus, Iexit); //defineInlinePrim("DOVAR", IbranchX|0, Idovar); //defineInlinePrim("DOLIT", IlitW, 0, 0, Iexit); defineInlinePrim("true", IlitX | 0xf); defineInlinePrim("false", IlitX); defineInlinePrim("(fill)", Ifill); defineInlinePrim("(cfill)", Icfill); defineInlinePrim("(cmove)", Icmove); defineInlinePrim("(LITERAL)", IlitW); defineInlinePrim("(DLITERAL)", IlitD_d); //defineInlinePrim("(s\")", IcontextFrom, CTX_PC, IlitX | 5, Iadd, Idup, I1plus, Iswap, Icload); defineInlinePrim("((s\"))", Irdrop, IatR, Idup, I1plus, Iswap, Icload, Idup, IRfrom, Iadd, I1plus, ItoR); define("(S\")", new TargetSQuote(defineEntry("(S\")"))); compileCall((ITargetWord) find("((s\"))")); compileOpcode(Iexit); defineInlinePrim("0<>", I0equ, Inot); defineInlinePrim("<>", Iequ, Inot); } private void definePrim(String string, int opcode) { define(string, new F99PrimitiveWord(defineEntry(string), opcode)); compileOpcode(opcode); compileByte(Iexit); } private void defineInlinePrim(String string, int... opcodes) { define(string, new F99InlineWord(defineEntry(string), opcodes)); for (int i : opcodes) compileOpcode(i); compileByte(Iexit); } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#defineEntry(java.lang.String) */ @Override public DictEntry defineEntry(String name) { DictEntry entry = super.defineEntry(name); startColonWord = 0; return entry; } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#defineColonWord(java.lang.String) */ @Override public TargetColonWord defineColonWord(String name) { TargetColonWord word = super.defineColonWord(name); startColonWord = getDP(); return word; } @Override public void initWordEntry() { alignDP(); } /* (non-Javadoc) * @see v9t9.forthcomp.words.TargetContext#doResolveRelocation(v9t9.forthcomp.RelocEntry) */ @Override protected int doResolveRelocation(RelocEntry reloc) throws AbortException { if (reloc.type == RelocType.RELOC_CALL_15S1) { int val = reloc.target; if ((val & 1) != 0) throw new AbortException("Call address is odd: " + HexUtils.toHex4(val)); val = ((val >> 1) & 0x7fff) | 0x8000; return val; } return super.doResolveRelocation(reloc); } public void compile(ITargetWord word) throws AbortException { word.getEntry().use(); if (word instanceof IPrimitiveWord) word.getCompilationSemantics().execute(hostCtx, this); else compileCall(word); } // /* (non-Javadoc) // * @see v9t9.forthcomp.words.TargetContext#compileLoad(int) // */ // @Override // protected void compileLoad(int bytes) { // if (bytes == 1) // compileOpcode(Icload); // else if (bytes == 2) // compileOpcode(Iload); // else if (bytes == 4) // compileOpcode(Iload_d); // else // assert false; // } /** * @param opcode */ public void compileOpcode(int opcode) { if (opcode >= 256) { stub16BitOpcode.use(); compileByte(opcode >> 8); compileByte(opcode & 0xff); } else { stub8BitOpcode.use(); compileByte(opcode); } } public void compileByte(int opcode) { // if (HostContext.DEBUG) // logfile.println("T>" + Integer.toHexString(getDP())+" C, " + Integer.toHexString(opcode)); writeChar(alloc(1), opcode); } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#compileDoubleLiteral(int) */ @Override public void compileDoubleLiteral(int valueLo, int valueHi, boolean isUnsigned, boolean optimize) { int value = (valueLo & 0xffff) | (valueHi << 16); if (optimize && value >= -8 && value < (isUnsigned ? 16 : 8)) { stub4BitLit.use(); compileOpcode(IlitX_d | (value & 0xf)); } else if (optimize && value >= -128 && value < (isUnsigned ? 256 : 128)) { stub8BitLit.use(); compileOpcode(IlitB_d); compileByte(value); } else { stub16BitLit.use(); stub16BitLit.use(); compileOpcode(IlitD_d); int ptr = alloc(4); writeCell(ptr, value & 0xffff); writeCell(ptr + 2, value >> 16); } } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#compileLiteral(int) */ @Override public void compileLiteral(int value, boolean isUnsigned, boolean optimize) { doCompileLiteral(value, isUnsigned, optimize).use(); } private DictEntry doCompileLiteral(int value, boolean isUnsigned, boolean optimize) { if (optimize && value >= -8 && value < (isUnsigned ? 16 : 8)) { compileByte(IlitX | (value & 0xf)); return stub4BitLit; } else if (optimize && value >= -128 && value < (isUnsigned ? 256 : 128)) { if (value < 0) stub8BitNegLit.use(); compileByte(IlitB); compileByte(value); return stub8BitLit; } else { if ((value & 0xff) == value) stub16BitU8Lit.use(); compileByte(IlitW); int ptr = alloc(2); writeCell(ptr, value & 0xffff); return stub16BitLit; } } @Override public void buildCell(int loc) { super.buildCell(loc); stub16BitLit.use(); } @Override public void buildChar(int val) { super.buildChar(val); stub8BitLit.use(); } /** * Export the state to a real machine * @param hostContext * @param machine * @param baseSP * @param baseRP * @throws AbortException */ public void doExportState(HostContext hostContext, IBaseMachine machine, int baseSP, int baseRP, int baseUP) throws AbortException { exportMemory(machine.getConsole()); CpuStateF99b cpu = (CpuStateF99b) machine.getCpu().getState(); cpu.setBaseSP((short) baseSP); Stack<Integer> stack = hostContext.getDataStack(); cpu.setSP((short) (baseSP - stack.size() * cellSize)); for (int i = 0; i < stack.size(); i++) machine.getConsole().writeWord(cpu.getSP() + i * 2, (short) (int) stack.get(stack.size() - i - 1)); cpu.setBaseRP((short) baseRP); stack = hostContext.getReturnStack(); cpu.setRP((short) (baseRP - stack.size() * cellSize)); for (int i = 0; i < stack.size(); i++) machine.getConsole().writeWord(cpu.getRP() + i * 2, (short) (int) stack.get(stack.size() - i - 1)); cpu.setBaseUP((short) baseUP); cpu.setUP((short) baseUP); } /** * Export the state to a real machine * @param hostContext * @param machine * @param baseSP * @param baseRP */ public void doImportState(HostContext hostContext, IBaseMachine machine, int baseSP, int baseRP) { importMemory(machine.getConsole()); CpuF99b cpu = (CpuF99b) machine.getCpu(); Stack<Integer> stack = hostContext.getDataStack(); stack.clear(); int curSP = ((CpuStateF99b)cpu.getState()).getSP() & 0xffff; while (baseSP > 0 && baseSP > curSP) { baseSP -= 2; stack.push((int) machine.getConsole().readWord(baseSP)); } stack = hostContext.getReturnStack(); stack.clear(); int curRP = ((CpuStateF99b)cpu.getState()).getRP() & 0xffff; while (curRP > 0 && baseRP > curRP) { curRP -= 2; stack.push((int) machine.getConsole().readWord(baseRP)); } } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#pushFixup() */ @Override public void pushFixup(HostContext hostContext) { super.pushFixup(hostContext); alloc(1); // assume short branch } @Override protected int writeJump(int opAddr, int target) throws AbortException { int diff = target - opAddr; // Opcode is already compiled as 1-byte branch, so diff is relative to offset // When we jump backward, measure from inst.pc, else from inst.pc + inst.size if (diff < -128 - 1 || diff >= 128) { throw hostCtx.abort("jump too long: " + diff); //System.err.println("jump too long: " + diff); } if (diff < -8 || diff >= 8 ) { stub8BitJump.use(); diff--; //System.out.println("@writeJumpOffs: " +opAddr + ": " + readChar(opAddr)); writeChar(opAddr, (diff & 0xff)); return 1; } else { stub4BitJump.use(); int newOp = readChar(opAddr - 1); if (newOp == IbranchB) newOp = IbranchX; else if (newOp == I0branchB) newOp = I0branchX; else throw hostCtx.abort("suspicious code sequence: " + Integer.toHexString(newOp)); writeChar(opAddr - 1, newOp | (diff & 0xf)); return 0; } } /* (non-Javadoc) * @see v9t9.tools.forthcomp.words.TargetContext#writeLoopJump(int) */ @Override protected void writeLoopJump(int opAddr) throws AbortException { writeJumpAlloc(opAddr, true); } @Override protected void writeJumpAlloc(int opAddr, boolean conditional) throws AbortException { int diff = opAddr - getDP(); int baseOpcode = conditional ? I0branchX : IbranchX; if (diff < -130 || diff >= 128) { stub16BitJump.use(); if (diff > 0) diff -= 3; else diff -= 2; baseOpcode = baseOpcode == IbranchX ? IbranchW : I0branchW; compileOpcode(baseOpcode); int ptr = alloc(cellSize); writeCell(ptr, diff); } else if (diff < -8 + 1 || diff >= 8 + 1) { stub8BitJump.use(); if (diff > 0) diff -= 2; else diff--; baseOpcode = baseOpcode == IbranchX ? IbranchB : I0branchB; compileOpcode(baseOpcode); compileByte((diff & 0xff)); } else { stub4BitJump.use(); diff--; compileOpcode(baseOpcode | (diff & 0xf)); } } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#defineCompilerWords(v9t9.forthcomp.HostContext) */ @Override public void defineCompilerWords(HostContext hostContext) { //define("HERE", defineForward("HERE", "<<built-in>>")); //define("BASE", defineForward("BASE", "<<built-in>>")); hostContext.define("FIELD,", new FieldComma()); hostContext.define("EXITI", new ExitI()); hostContext.define("CTX_SP", new HostLiteral(CTX_SP, false)); hostContext.define("CTX_SP0", new HostLiteral(CTX_SP0, false)); hostContext.define("CTX_RP", new HostLiteral(CTX_RP, false)); hostContext.define("CTX_RP0", new HostLiteral(CTX_RP0, false)); hostContext.define("CTX_UP", new HostLiteral(CTX_UP, false)); hostContext.define("CTX_LP", new HostLiteral(CTX_LP, false)); hostContext.define("CTX_PC", new HostLiteral(CTX_PC, false)); } public void compileUser(TargetUserVariable var) { int index = var.getOffset(); if (index < 256) { compileOpcode(Iupidx); compileByte(index); } else { doCompileLiteral(index, false, true); compileOpcode(Iuser); } } /* private int getLocalOffs(int index) { DictEntry entry = ((ITargetWord) getLatest()).getEntry(); int offs = entry.getLocalCount() - index; return -offs * 2; } @Override public void ensureLocalSupport(HostContext hostContext) throws AbortException { if (lpUser == null) { lpUser = (TargetUserVariable) find("LP"); if (lpUser == null) { lpUser = defineUser("LP", 1); HostContext subContext = new HostContext(this); hostContext.copyTo(subContext); subContext.getStream().push( "false <export\n"+ ": (>LOCALS) LP @ RP@ LP ! ; \\ caller pushes R> \n" + ": (LOCALS>) R> LP @ RP! R> LP ! >R ; \n" + "export>\n"); ForthComp comp = new ForthComp(subContext, this); comp.parse(); if (comp.getErrors() > 0) throw hostContext.abort("Failed to compile support code"); hostContext.copyFrom(subContext); } } } @Override public void compileSetupLocals() throws AbortException { DictEntry entry = ((ITargetWord) getLatest()).getEntry(); if (entry.hasLocals()) throw new AbortException("cannot add more locals now"); compile(require("(>LOCALS)")); compileOpcode(ItoR); // save old LP } @Override public void compileCleanupLocals() throws AbortException { DictEntry entry = (getLatest()).getEntry(); if (entry.hasLocals()) { compile(require("(LOCALS>)")); } } @Override public void compileInitLocal(int index) throws AbortException { compileOpcode(ItoR); } @Override public void compileLocalAddr(int index) { compileUser(lpUser); compileOpcode(Iload); compileLiteral(getLocalOffs(index), false, true); compileOpcode(Iadd); } */ public boolean isLocalSupportAvailable(HostContext hostContext) throws AbortException { return true; } @Override public void compileSetupLocals(HostContext hostContext) throws AbortException { DictEntry entry = ((ITargetWord) getLatest()).getEntry(); if (entry.hasLocals()) throw new AbortException("cannot add more locals now"); compileOpcode(ItoLocals); } @Override public void compileCleanupLocals(HostContext hostContext) throws AbortException { DictEntry entry = ((ITargetWord) getLatest()).getEntry(); if (entry.hasLocals()) { compileOpcode(IfromLocals); } } @Override public void compileAllocLocals(int count) throws AbortException { compileOpcode(Ilalloc); compileByte(count); } @Override public void compileLocalAddr(int index) { compileOpcode(Ilocal); compileByte(index); } @Override public void compileFromLocal(int index) throws AbortException { compileOpcode(Ilpidx); compileByte(index); } @Override public void compileToLocal(int index) throws AbortException { compileLocalAddr(index); compileByte(Istore); } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#compileDoConstant(int, int) */ @Override public void compileDoConstant(int value, int cells) throws AbortException { if (cells == 1) compileLiteral(value, false, true); else if (cells == 2) compileDoubleLiteral(value & 0xffff, value >> 16, false, true); else throw new UnsupportedOperationException(); compileOpcode(Iexit); } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#compileDoUser(int) */ @Override public void compileDoUser(int offset) { if (offset < 256) { compileOpcode(Iupidx); compileByte(offset); } else { doCompileLiteral(offset, false, true); compileOpcode(Iuser); } compileOpcode(Iexit); } public void compileDoRomDefer(int offset) { throw new UnsupportedOperationException(); } /** * @param hostContext TODO * @throws AbortException * */ public void compileExitI(HostContext hostContext) throws AbortException { if (((ITargetWord) getLatest()).getEntry().hasLocals()) compileCleanupLocals(hostContext); compileOpcode(Iexiti); } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#compileDoValue(int, int) */ @Override public int compilePushValue(int cells, int value) throws AbortException { int loc; if (cells == 1) { compileOpcode(IlitW); loc = alloc(cellSize); compileOpcode(Iexit); //compile(require("DOLIT")); } else { compileOpcode(IlitD_d); loc = alloc(cellSize * cells); compileOpcode(Iexit); //compile(require("DODLIT")); } if (cells == 1) { writeCell(loc, value); stub16BitLit.use(); } else if (cells == 2) { writeCell(loc, value & 0xffff); writeCell(loc + 2, value >> 16); stub16BitLit.use(); stub16BitLit.use(); } else throw new AbortException("unhandled size: " +cells); return loc; } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#compileWordParamAddr(v9t9.forthcomp.TargetValue) */ @Override public void compileWordParamAddr(ITargetWord word) { stub16BitLit.use(); doCompileLiteral(((ITargetWord)word).getEntry().getParamAddr(), true, true); } /* (non-Javadoc) * @see v9t9.forthcomp.TargetContext#compileWordXt(v9t9.forthcomp.ITargetWord) */ @Override public void compileTick(ITargetWord word) { stub16BitAddr.use(); compileByte(IlitW); int ptr = alloc(cellSize); int reloc = addRelocation(ptr, RelocType.RELOC_ABS_ADDR_16, word.getEntry().getContentAddr()); writeCell(ptr, reloc); } /* (non-Javadoc) * @see v9t9.forthcomp.words.TargetContext#compileCall(v9t9.forthcomp.ITargetWord) */ @Override public void compileCall(ITargetWord word) { stubCall.use(); int pc = alloc(cellSize); int reloc = addRelocation(pc, RelocType.RELOC_CALL_15S1, word.getEntry().getContentAddr()); writeCell(pc, reloc); } /* (non-Javadoc) * @see v9t9.forthcomp.words.TargetContext#compileDoVar() */ @Override protected void compileDoVar() { compileOpcode(IbranchX|0); compileOpcode(Idovar); } public int buildDoes(HostContext hostContext) throws AbortException { // must be call'able alignDP(); int addr = getDP(); compileOpcode(IRfrom); return addr; } /* (non-Javadoc) * @see v9t9.forthcomp.words.TargetContext#compileDoes(int) */ @Override public void compileDoes(HostContext hostContext, DictEntry entry, int targetDP) throws AbortException { /* // paramAddr is after EXIT int dataSize = (getDP() - entry.getParamAddr()); if (dataSize >= 8) { throw hostContext.abort("cannot invoke DOES> on " + entry.getName() + " since its data is too large"); } writeChar(entry.getParamAddr() - 1, IbranchX | dataSize); compileOpcode(IbranchW); int reloc = addRelocation(dp, RelocType.RELOC_ABS_ADDR_16, targetDP, entry.getName()); compileCell(reloc); //compileCell(targetDP); */ addRelocation(entry.getContentAddr(), RelocType.RELOC_CALL_15S1, targetDP); //compileCell(reloc); } /* (non-Javadoc) * @see v9t9.tools.forthcomp.words.TargetContext#compileExit(v9t9.tools.forthcomp.HostContext) */ @Override public void compileExit(HostContext hostContext) throws AbortException { super.compileExit(hostContext); require(";S").getCompilationSemantics().execute(hostContext, this); // int endDP = getDP(); // if (startColonWord != 0) { // peephole(startColonWord, endDP); // } } /* (non-Javadoc) * @see v9t9.tools.forthcomp.ITargetContext#compileEndCode(java.lang.String) */ @Override public void compileEndCode() { compileOpcode(Iexit); } /** * @param startColonWord2 * @param endDP * @return */ protected void peephole(int start, int end) { if (cellWord == null) cellWord = (ITargetWord) find("cell"); if (cellPlusWord == null) cellPlusWord = (ITargetWord) find("cell+"); setDP(start); while (start < end) { start = peepholePattern(start); } } protected void peepByte(int start) { writeChar(getDP(), readChar(start)); incDP(1); } /** * @param start * @return */ protected int peepholePattern(int start) { int addr = findReloc(start); if (addr == 0) { // not a call but a lit int op = readChar(start); if ((op & 0xf0) == InstF99b.I0branchX) { // fixup a branch peepByte(start++); } else if (op == InstF99b.I0branchB) { peepByte(start++); peepByte(start++); } else if (op == InstF99b.I0branchW) { peepByte(start++); peepByte(start++); peepByte(start++); } else if (op == InstF99b.IbranchX) { peepByte(start++); } else if (op == InstF99b.IbranchB) { peepByte(start++); peepByte(start++); } else if (op == InstF99b.IbranchW) { peepByte(start++); peepByte(start++); peepByte(start++); } else { peepByte(start++); } return start; } if (cellWord != null && addr == cellWord.getEntry().getAddr()) { writeChar(getDP(), InstF99b.IlitX + 2); removeReloc(start++); incDP(1); return start + 2; } if (cellPlusWord != null && addr == cellPlusWord.getEntry().getAddr()) { writeChar(getDP(), InstF99b.I2plus); removeReloc(start); incDP(1); return start + 2; } peepByte(start++); return start; } /** * @param i */ private void incDP(int i) { setDP(getDP() + i); } /* (non-Javadoc) * @see v9t9.tools.forthcomp.words.TargetContext#isNativeDefinition() */ @Override public boolean isNativeDefinition() { return true; } /* (non-Javadoc) * @see v9t9.tools.forthcomp.TargetContext#isLikelyAddress(int) */ @Override protected boolean isLikelyAddress(int value) { return value >= 0x4000 && value <= 0xFF00; } /* (non-Javadoc) * @see v9t9.tools.forthcomp.BaseGromTargetContext#createGromDictEntry(int, int, java.lang.String) */ @Override protected DictEntry createGromDictEntry(int size, int entryAddr, String name) { // link (=>xt), name int dictSize = cellSize + 1 + name.length(); DictEntry entry = new F99bGromDictEntry(dictSize, entryAddr, name, gp); gp += dictSize; return entry; } }