--- a
+++ b/trunk/MMix/MMix.AssemblerLib/Assembler.hpp
@@ -0,0 +1,201 @@
+#ifndef MMIX_ASSEMBLERLIB_ASSEMBLER_INCLUDED
+#define MMIX_ASSEMBLERLIB_ASSEMBLER_INCLUDED
+#include <MMix.AssemblerLib/Expression.hpp>
+#include <MMix.AssemblerLib/AssemblyOp.hpp>
+#include <MMix.Machine/BinaryWriter.hpp>
+#include <map>
+
+namespace MMix { namespace AssemblerLib {
+
+using MMix::Machine::String;
+using MMix::Machine::Octa;
+using MMix::Machine::Byte;
+using MMix::Machine::byte;
+using MMix::Machine::Wyde;
+using MMix::Machine::wyde;
+using MMix::Machine::Tetra;
+using MMix::Machine::tetra;
+using MMix::Machine::FutureReferencePtr;
+using MMix::Machine::BinaryWriter;
+using MMix::Machine::SymbolPtr;
+using Soul::Parsing::Position;
+
+const int ALIGN_SHIFT = 0;
+const int ALIGN_BITS = 4;
+const int ALIGN_MASK = (1 << ALIGN_BITS) - 1;
+
+const int ZERO_ARGS = 0;
+const int ONE_ARG = 1;
+const int TWO_ARGS = 2;
+const int THREE_ARGS = 2;
+const int MANY_ARGS = 4;
+
+const int MIN_ARGS_SHIFT = ALIGN_SHIFT + ALIGN_BITS;
+const int MIN_ARGS_BITS = 3;
+const int MIN_ARGS_MASK  = (1 << MIN_ARGS_BITS) - 1;
+
+const int MAX_ARGS_SHIFT = MIN_ARGS_SHIFT + MIN_ARGS_BITS;
+const int MAX_ARGS_BITS = 3;
+const int MAX_ARGS_MASK  = (1 << MAX_ARGS_BITS) - 1;
+
+const int XREG_SHIFT = MAX_ARGS_SHIFT + MAX_ARGS_BITS;
+const int XREG_BITS = 1;
+const int XREG_MASK = (1 << XREG_BITS) - 1;
+
+const int YREG_SHIFT = XREG_SHIFT + XREG_BITS;
+const int YREG_BITS = 1;
+const int YREG_MASK = (1 << YREG_BITS) - 1;
+
+const int ZREG_SHIFT = YREG_SHIFT + YREG_BITS;
+const int ZREG_BITS = 1;
+const int ZREG_MASK = (1 << ZREG_BITS) - 1;
+
+const int XIGNORE_SHIFT = ZREG_SHIFT + ZREG_BITS;
+const int XIGNORE_BITS = 1;
+const int XIGNORE_MASK = (1 << XIGNORE_BITS) - 1;
+
+const int YIGNORE_SHIFT = XIGNORE_SHIFT + XIGNORE_BITS;
+const int YIGNORE_BITS = 1;
+const int YIGNORE_MASK = (1 << YIGNORE_BITS) - 1;
+
+const int ZIGNORE_SHIFT = YIGNORE_SHIFT + YIGNORE_BITS;
+const int ZIGNORE_BITS = 1;
+const int ZIGNORE_MASK = (1 << ZIGNORE_BITS) - 1;
+
+const int YIMMEDIATE_SHIFT = ZIGNORE_SHIFT + ZIGNORE_BITS;
+const int YIMMEDIATE_BITS = 1;
+const int YIMMEDIATE_MASK = (1 << YIMMEDIATE_BITS) - 1;
+
+const int ZIMMEDIATE_SHIFT = YIMMEDIATE_SHIFT + YIMMEDIATE_BITS;
+const int ZIMMEDIATE_BITS = 1;
+const int ZIMMEDIATE_MASK = (1 << ZIMMEDIATE_BITS) - 1;
+
+const int YZIMMEDIATE_SHIFT = ZIMMEDIATE_SHIFT + ZIMMEDIATE_BITS;
+const int YZIMMEDIATE_BITS = 1;
+const int YZIMMEDIATE_MASK = (1 << YZIMMEDIATE_BITS) - 1;
+
+const int RELATIVE_ADDDRESS_SHIFT = YZIMMEDIATE_SHIFT + YZIMMEDIATE_BITS;
+const int RELATIVE_ADDDRESS_BITS = 1;
+const int RELATIVE_ADDDRESS_MASK = (1 << RELATIVE_ADDDRESS_BITS) - 1;
+
+const int MEMYZ_SHIFT = RELATIVE_ADDDRESS_SHIFT + RELATIVE_ADDDRESS_BITS;
+const int MEMYZ_BITS = 1;
+const int MEMYZ_MASK = (1 << MEMYZ_BITS) - 1;
+
+const int SPEC_SHIFT = MEMYZ_SHIFT + MEMYZ_BITS;
+const int SPEC_BITS = 1;
+const int SPEC_MASK = (1 << SPEC_BITS) - 1;
+
+const int NOLABEL_SHIFT = SPEC_SHIFT + SPEC_BITS;
+const int NOLABEL_BITS = 1;
+const int NOLABEL_MASK = (1 << NOLABEL_BITS) - 1;
+
+inline tetra Alignment(int alignment) { return alignment << ALIGN_SHIFT; }
+inline tetra MinArgs(int numArgs) { return numArgs << MIN_ARGS_SHIFT; }
+inline tetra MaxArgs(int numArgs) { return numArgs << MAX_ARGS_SHIFT; }
+inline tetra XReg() { return 1 << XREG_SHIFT; }
+inline tetra YReg() { return 1 << YREG_SHIFT; }
+inline tetra ZReg() { return 1 << ZREG_SHIFT; }
+inline tetra XZReg() { return XReg() | ZReg(); }
+inline tetra XYReg() { return XReg() | YReg(); }
+inline tetra XYZReg() { return XReg() | YReg() | ZReg(); }
+inline tetra XIgnore() { return 1 << XIGNORE_SHIFT; }
+inline tetra YIgnore() { return 1 << YIGNORE_SHIFT; }
+inline tetra ZIgnore() { return 1 << ZIGNORE_SHIFT; }
+inline tetra XYZIgnore() { return  XIgnore() | YIgnore() | ZIgnore(); }
+inline tetra YImmediate() { return 1 << YIMMEDIATE_SHIFT; }
+inline tetra ZImmediate() { return 1 << ZIMMEDIATE_SHIFT; }
+inline tetra YZImmediate() { return 1 << YZIMMEDIATE_SHIFT; }
+inline tetra RelativeAddress() { return 1 << RELATIVE_ADDDRESS_SHIFT; }
+inline tetra MemYZ() { return 1 << MEMYZ_SHIFT; }
+inline tetra Special() { return 1 << SPEC_SHIFT; }
+inline tetra NoLabel() { return 1 << NOLABEL_SHIFT; }
+
+class Opcode
+{
+public:
+    Opcode(): name(), inst(), flags() {}
+    Opcode(const String& name_, wyde inst_, tetra flags_): name(name_), inst(inst_), flags(flags_) {}
+    const String& Name() const { return name; }
+    wyde Inst() const { return inst; }
+    tetra Flags() const { return flags; }
+    bool IsPseudoOp() const { return inst >= 256; }
+    int Alignment() const { return (flags >> ALIGN_SHIFT) & ALIGN_MASK; }
+    int MinArgs() const { return (flags >> MIN_ARGS_SHIFT) & MIN_ARGS_MASK; }
+    int MaxArgs() const { return (flags >> MAX_ARGS_SHIFT) & MAX_ARGS_MASK; }
+    bool XReg() const { return (flags >> XREG_SHIFT) & XREG_MASK; }
+    bool YReg() const { return (flags >> YREG_SHIFT) & YREG_MASK; }
+    bool ZReg() const { return (flags >> ZREG_SHIFT) & ZREG_MASK; }
+    bool XYReg() const { return XReg() && YReg(); }
+    bool XZReg() const { return XReg() && ZReg(); }
+    bool XYZReg() const { return XReg() && YReg() && ZReg(); }
+    bool XIgnore() const { return (flags >> XIGNORE_SHIFT) & XIGNORE_MASK; }
+    bool YIgnore() const { return (flags >> YIGNORE_SHIFT) & YIGNORE_MASK; }
+    bool ZIgnore() const { return (flags >> ZIGNORE_SHIFT) & ZIGNORE_MASK; }
+    bool XYZIgnore() const { return XIgnore() && YIgnore() && ZIgnore(); }
+    bool YImmediate() const { return (flags >> YIMMEDIATE_SHIFT) & YIMMEDIATE_MASK; }
+    bool ZImmediate() const { return (flags >> ZIMMEDIATE_SHIFT) & ZIMMEDIATE_MASK; }
+    bool YZImmediate() const { return (flags >> YZIMMEDIATE_SHIFT) & YZIMMEDIATE_MASK; }
+    bool RelativeAddress() const { return (flags >> RELATIVE_ADDDRESS_SHIFT) & RELATIVE_ADDDRESS_MASK; }
+    bool MemYZ() const { return (flags >> MEMYZ_SHIFT) & MEMYZ_MASK; }
+    bool Special() const { return (flags >> SPEC_SHIFT) & SPEC_MASK; }
+    bool NoLabel() const { return (flags >> NOLABEL_SHIFT) & NOLABEL_MASK; }
+private:
+    String name;
+    wyde inst;
+    tetra flags;
+};
+
+bool IsLocalLabel(const String& label);
+
+class Assembler
+{
+public:
+    Assembler(const String& mmoFileName_);
+    Octa Loc() const { return loc; }
+    Octa& Loc() { return loc; }
+    Octa OLoc() const { return oloc; }
+    Octa& OLoc() { return oloc; }
+    const Opcode& GetOpcode(const String& opcodeName, const String& content, const String& fileName, const Position& position);
+    void Assemble(const String& label, const Opcode& opcode, const OperandListPtr& operands, 
+        const String& content, const String& fileName, const Position& position);
+    void StartAssemble();
+    void EndAssemble();
+private:
+    Octa loc;
+    Octa oloc;
+    BinaryWriter writer;
+    typedef std::map<String, Opcode> OpcodeMap;
+    typedef OpcodeMap::const_iterator OpcodeMapIt;
+    OpcodeMap opcodes;
+    void Align(int alignment);
+    void Synchronize();
+    void ProcessLabel(const String& label, const String& content, const String& fileName, const Position& position);
+    void FixFutureReferences(const SymbolPtr& symbol);
+    void AssembleOneArg(Tetra& t, const Opcode& op, const OperandPtr& arg, const String& label,
+        const String& content, const String& fileName, const Position& position);
+    void AssembleTwoArgs(Tetra& t, const Opcode& op, const OperandPtr& arg0, const OperandPtr& arg1, 
+        const String& content, const String& fileName, const Position& position);
+    void AssembleThreeArgs(Tetra& t, const Opcode& op, const OperandPtr& arg0, const OperandPtr& arg1, const OperandPtr& arg2, 
+        const String& content, const String& fileName, const Position& position);
+    void AssembleManyArgs(const Opcode& op, const OperandListPtr& operands, 
+        const String& content, const String& fileName, const Position& position);
+    void AssembleXYZRelative(Tetra& t, const Opcode& op, const OperandPtr& arg,
+        const String& content, const String& fileName, const Position& position);
+    void AssembleYZRelative(Tetra& t, const Opcode& op, const OperandPtr& arg,
+        const String& content, const String& fileName, const Position& position);
+    void AssembleYZMemory(Tetra& t, const Opcode& op, const OperandPtr& arg,
+        const String& content, const String& fileName, const Position& position);
+    void AssembleX(Tetra& t, const Opcode& op, const OperandPtr& x,
+        const String& content, const String& fileName, const Position& position);
+    void AssembleY(Tetra& t, const Opcode& op, const OperandPtr& y,
+        const String& content, const String& fileName, const Position& position);
+    void AssembleZ(Tetra& t, const Opcode& op, const OperandPtr& z,
+        const String& content, const String& fileName, const Position& position);
+    void PredefineSymbols();
+};
+
+} } // namespace MMIx::AssemblerLib
+
+#endif // MMIX_ASSEMBLER_ASSEMBLER_INCLUDED
+