diff -NaHudr fparser-jittest-1.1/Makefile fparser-jittest-1.2/Makefile
--- fparser-jittest-1.1/Makefile	2008-01-10 18:27:59.000000000 +0200
+++ fparser-jittest-1.2/Makefile	2008-01-11 06:43:21.000000000 +0200
@@ -1,11 +1,13 @@
 include Makefile.sets
 
 ARCHDIR=archives/
-ARCHNAME=fparser-jittest-1.1
+ARCHNAME=fparser-jittest-1.2
 ARCHFILES=jittest.cc calculator.hh compiler.hh formula.hh \
 	interpreter.hh opcodes.hh \
 	Makefile.sets Makefile.sets.in configure
 
+OPTIM+=-fno-inline
+
 jittest: jittest.o
 	$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS) $(LDLIBS)
 
diff -NaHudr fparser-jittest-1.1/Makefile.sets fparser-jittest-1.2/Makefile.sets
--- fparser-jittest-1.1/Makefile.sets	2008-01-09 21:49:19.000000000 +0200
+++ fparser-jittest-1.2/Makefile.sets	2008-01-11 06:43:12.000000000 +0200
@@ -24,18 +24,18 @@
 
 #####
 # These options were set by ./configure
-# at Wed Jan  9 20:52:35 EET 2008
-# for Linux oktober 2.6.20-gentoo-r7 #2 Thu May 10 18:58:39 EEST 2007 i686 AMD Athlon(tm) XP 2000+ AuthenticAMD GNU/Linux
+# at Fri Jan 11 06:43:11 EET 2008
+# for Linux chii 2.6.23.1 #1 SMP Wed Oct 31 02:24:16 EET 2007 x86_64 GNU/Linux
 # To change, run ./configure again.
 #
-CC=icc
-CPP=icc
-CXX=icc
-OPTIM +=  -ipo
-CPPFLAGS +=  -w1 -inline-level=2
-LDFLAGS +=  -L/opt/intel/cc/10.0.026/bin/lib -lirc -lguide -lpthread -lstdc++
-WARNINGS += 
-CWARNINGS += 
-CXXWARNINGS += 
+CC=gcc-4.2
+CPP=cpp-4.2
+CXX=g++-4.2
+OPTIM +=  -ftree-vectorize -ffast-math
+CPPFLAGS += 
+LDFLAGS += 
+WARNINGS +=  -Wall -Wundef -Wcast-qual -Wpointer-arith -Wconversion -Wwrite-strings -Wsign-compare -Wredundant-decls -Winit-self -Wextra -Wcast-align -Wformat
+CWARNINGS +=  -Waggregate-return -Wshadow -Winline -Wstrict-prototypes -Wmissing-prototypes
+CXXWARNINGS +=  -Woverloaded-virtual -Weffc++
 
 
diff -NaHudr fparser-jittest-1.1/compiler.hh fparser-jittest-1.2/compiler.hh
--- fparser-jittest-1.1/compiler.hh	2008-01-10 18:27:39.000000000 +0200
+++ fparser-jittest-1.2/compiler.hh	2008-01-11 08:13:54.000000000 +0200
@@ -1,5 +1,6 @@
 #include <stdint.h>
 #include <vector>
+#include <set>
 
 #ifdef unix
 # include <sys/mman.h>
@@ -10,17 +11,26 @@
 #endif
 
 static const unsigned char SSE_NegPattern[16] = {0,0,0,0, 0,0,0,0x80, 0,0,0,0, 0,0,0,0};
+static const double FP_Constant_One = 1.0;
 
 class Compiler: public Calculator
 {
 public:
-    Compiler(const opcode* op, size_t n)
-        : CodeBuffer(), Code(0)
+    Compiler(const opcode* op, size_t n, bool UseSSE)
+        : CodeBuffer(), name("Compiler"), Code(0), CodePtr(0)
     {
-        SynthesizeCode_SimpleFP(op, op+n);
-        
-        //static const int StackRegisters[16] = {0,1,2,3,4,5,6,7, 8,9,10,11,12,13,14,15};
-        //SynthesizeCode_SimpleSSE(op, op+n, StackRegisters);
+        if(UseSSE)
+        {
+            CodeSynth synth(true, *this);
+            SynthesizeCode_Generic(op, op+n, synth);
+            name = "Compiler (SSE)";
+        }
+        else
+        {
+            CodeSynth synth(false, *this);
+            SynthesizeCode_Generic(op, op+n, synth);
+            name = "Compiler (387)";
+        }        
         
         Code = new unsigned char[ CodeBuffer.size() + PAGE_SIZE*3 ];
         
@@ -30,7 +40,7 @@
         
         std::memcpy(CodePtr, &CodeBuffer[0], CodeBuffer.size());
         
-        //fwrite(CodePtr, 1, CodeBuffer.size(), stdout);
+        fwrite(CodePtr, 1, CodeBuffer.size(), stdout);
         
     #ifdef unix
         mprotect(CodePtr, CodeBuffer.size(), PROT_EXEC|PROT_READ);
@@ -46,7 +56,7 @@
     
     virtual std::string Identify() const
     {
-        return "Compiler";
+        return name;
     }
     
     virtual double Calc() const
@@ -77,11 +87,644 @@
                   A = A*y
                   A = A+Z
     */
+    
+    size_t SynthStackBegin(size_t doubles_required)
+    {
+        size_t stack_required = (doubles_required + 1) * 8;
+        
+        #ifdef __x86_64
+            Synth(0x48, 0x81, 0xEC);
+            SynthI32(stack_required);  // sub rsp, n*8
+        #else
+            stack_required += 4; // improve aligning a bit                
+            Synth(0x81, 0xEC);
+            SynthI32(stack_required);  // sub esp, n*8
+        #endif
+        
+        return stack_required;
+    }
+    void SynthStackEnd(size_t stack_required)
+    {
+        #ifdef __x86_64
+            Synth(0x48, 0x81, 0xC4);
+            SynthI32(stack_required);  // add rsp, n*8
+        #else
+            Synth(0x81, 0xC4);
+            SynthI32(stack_required);  // add esp, n*8
+        #endif
+    }
+    
+    class CodeSynth
+    {
+    private:
+        bool SSE;
+        
+        struct Location
+        {
+            enum { ST, XMM, Mem, Stack } Loc;
+            //union {
+            int           st_no;
+            int           xmm_no;
+            int           stackoffs;
+            const double* memaddr;
+            bool          expected_reuse;
+            //};
+            
+            Location(): Loc(Mem), st_no(0),xmm_no(0),stackoffs(0),memaddr(0),
+                        expected_reuse(false) { }
+        };
+        std::vector<Location> stack; // calculator stack
+        std::set<int> Stack_Use;     // memory stack
+        int fpu_stack_depth;
+        Compiler& com;
+        std::vector<const void*> basereg_use;
+        
+    private:
+        
+    public:
+        CodeSynth(bool sse, Compiler& comp)
+            : SSE(sse), stack(), Stack_Use(),
+              fpu_stack_depth(0), com(comp),
+              basereg_use(16, (const void*)0)
+        {
+        }
+        
+        void GenAdd(bool by_itself)
+        {
+            StackDump("GenAdd");
+            Location& top = stack[stack.size()-1];
+            if(by_itself)
+            {
+                if(SSE && !(top.Loc == Location::ST && top.st_no == 0) )
+                {
+                    int xmm = RequireXMM(0);
+                    SynthXMM_XMM(0xF2,0x0F,0x58, xmm, xmm);
+                }
+                else
+                    { RequireST(0); com.Synth(0xD8, 0xC0); } //fadd
+            }
+            else
+            {
+                if(SSE)
+                {
+                    int cur = RequireXMM(1);
+                    if(top.Loc == Location::Mem)
+                        SynthXMM_Mem(0xF2,(cur&8)?0x44:0, 0x0F,0x58,(cur&7)*8, top.memaddr, top.expected_reuse);
+                    else
+                        SynthXMM_XMM(0xF2,0x0F,0x58, cur, RequireXMM(0));
+                }
+                else
+                {
+                    RequireST(1); RequireST(0); com.Synth(0xDE, 0xC1); //faddp
+                }
+                DidPop();
+            }
+        }
+        void GenSub(bool by_itself)
+        {
+            StackDump("GenSub");
+            Location& top = stack[stack.size()-1];
+            if(by_itself) ;
+            else
+            {
+                if(SSE)
+                {
+                    int cur = RequireXMM(1);
+                    if(top.Loc == Location::Mem)
+                        SynthXMM_Mem(0xF2,(cur&8)?0x44:0, 0x0F,0x5C,(cur&7)*8, top.memaddr, top.expected_reuse);
+                    else
+                        SynthXMM_XMM(0xF2,0x0F,0x5C, cur, RequireXMM(0));
+                }
+                else
+                {
+                    RequireST(1); RequireST(0); com.Synth(0xDE, 0xE9); //fsubp
+                }
+                DidPop();
+            }
+        }
+        void GenMul(bool by_itself)
+        {
+            StackDump("GenMul");
+            Location& top = stack[stack.size()-1];
+            if(by_itself)
+            {
+                if(SSE && !(top.Loc == Location::ST && top.st_no == 0) )
+                {
+                    int xmm = RequireXMM(0);
+                    SynthXMM_XMM(0xF2,0x0F,0x59, xmm, xmm);
+                }
+                else
+                    { RequireST(0); com.Synth(0xD8, 0xC8); } //fmul
+            }
+            else
+            {
+                if(SSE)
+                {
+                    int cur = RequireXMM(1);
+                    if(top.Loc == Location::Mem)
+                        SynthXMM_Mem(0xF2,(cur&8)?0x44:0, 0x0F,0x59,(cur&7)*8, top.memaddr, top.expected_reuse);
+                    else
+                        SynthXMM_XMM(0xF2,0x0F,0x59, cur, RequireXMM(0));
+                }
+                else
+                {
+                    RequireST(1); RequireST(0); com.Synth(0xDE, 0xC9); //fmulp
+                }
+                DidPop();
+            }
+        }
+        void GenDiv(bool by_itself)
+        {
+            StackDump("GenDiv");
+            Location& top = stack[stack.size()-1];
+            if(by_itself) ;
+            else
+            {
+                if(SSE)
+                {
+                    int cur = RequireXMM(1);
+                    if(top.Loc == Location::Mem)
+                        SynthXMM_Mem(0xF2,(cur&8)?0x44:0, 0x0F,0x5E,(cur&7)*8, top.memaddr, top.expected_reuse);
+                    else
+                        SynthXMM_XMM(0xF2,0x0F,0x5E, cur, RequireXMM(0));
+                }
+                else
+                {
+                    RequireST(1); RequireST(0); com.Synth(0xDE, 0xF9); //fdivp
+                }
+                DidPop();
+            }
+        }
+        void GenRDiv(bool by_itself)
+        {
+            if(by_itself) ;
+            else
+            {
+                RequireST(1); RequireST(0); com.Synth(0xDE, 0xF1); // fdivrp
+                DidPop();
+            }
+        }
+        void GenDup()
+        {
+            StackDump("GenDup");
+            if(SSE)
+            {
+                int newxmm = GetFreeXMM();
+                stack.push_back( CopyToXMM( stack[stack.size()-1], newxmm) );
+            }
+            else
+            {
+                RequireST(0);
+                RoomST(1);
+                com.Synth(0xD9, 0xC0); // fld st0
+                GotST();
+            }
+        }
+        void GenNeg()
+        {
+            StackDump("GenNeg");
+            Location& top = stack[stack.size()-1];
+            if(SSE && !(top.Loc == Location::ST && top.st_no == 0) )
+            {
+                int xmm = RequireXMM(0);
+                SynthXMM_Mem(0x66, (xmm&8)?0x44:0, 0x0F,0x57,(xmm&7)*8, SSE_NegPattern, false);
+            }
+            else
+            {
+                RequireST(0);
+                com.Synth(0xD9, 0xE0); // fchs st0
+            }
+        }
+        void GenSqrt()
+        {
+            StackDump("GenSqrt");
+            Location& top = stack[stack.size()-1];
+            if(SSE && !(top.Loc == Location::ST && top.st_no == 0) )
+            {
+                if(top.Loc == Location::Mem)
+                {
+                    int xmm = GetFreeXMM();
+                    SynthXMM_Mem(0xF2,(xmm&8)?0x44:0, 0x0F,0x51,(xmm&7)*8, top.memaddr, top.expected_reuse);
+                    top.Loc    = Location::XMM;
+                    top.xmm_no = xmm;
+                }
+                else
+                {
+                    int xmm = RequireXMM(0);
+                    SynthXMM_XMM(0xF2,0x0F,0x51, xmm, xmm);
+                }
+            }
+            else
+            {
+                RequireST(0);
+                com.Synth(0xD9, 0xFA); // fsqrt st0
+            }
+        }
+        void GenConstLoad(const double& immed)
+        {
+            StackDump("GenConstLoad");
+            if(SSE)
+            {
+                if(immed == 0.0)
+                    { int xmmno = GetFreeXMM();
+                      /* zero the register with xorps xmm,xmm */
+                      SynthXMM_XMM(0, 0x0F,0x57, xmmno, xmmno);
+                      Location loc;
+                      loc.Loc     = Location::XMM;
+                      loc.xmm_no  = xmmno;
+                      stack.push_back(loc);
+                      return;
+                    }
+                goto JustLoadFromMem;
+            }
+            if(immed == 1.0)
+                { com.Synth(0xD9, 0xE8); GotST(); } // fld1
+            else if(immed == 3.3219280948873623478)
+                { com.Synth(0xD9, 0xE9); GotST(); } // log2(10)
+            else if(immed == 1.4426950408889634074)
+                { com.Synth(0xD9, 0xEA); GotST(); } // log2(e)
+            else if(immed == 3.14159265358979323846)
+                { com.Synth(0xD9, 0xEB); GotST(); } // fldpi
+            else if(immed == 0.86858896380650365529)
+                { com.Synth(0xD9, 0xEC); GotST(); } // log10(2)
+            else if(immed == 0.69314718055994530943)
+                { com.Synth(0xD9, 0xED); GotST(); } // loge(2)
+            else if(immed == 0.0)
+                { com.Synth(0xD9, 0xEE); GotST(); } // fldz
+            else
+            {
+            JustLoadFromMem:
+                Location loc;
+                loc.Loc     = Location::Mem;
+                loc.memaddr = &immed;
+                loc.expected_reuse = false;
+                stack.push_back(loc);
+            }
+        }
+        void GenVarLoad(const double& value)
+        {
+            StackDump("GenVarLoad");
+            Location loc;
+            loc.Loc     = Location::Mem;
+            loc.memaddr = &value;
+            loc.expected_reuse = true;
+            stack.push_back(loc);
+        }
+        
+        void StackDump(const std::string& forwhom) const
+        {
+            std::cerr << forwhom << ":";
+            for(size_t a=0, b=stack.size(); a<b; ++a)
+            {
+                std::cerr << " [";
+                const Location& loc = stack[a];
+                switch(loc.Loc)
+                {
+                    case Location::ST:
+                        std::cerr << "ST" << loc.st_no; break;
+                    case Location::XMM:
+                        std::cerr << "XMM" << loc.xmm_no; break;
+                    case Location::Mem:
+                        std::cerr << loc.memaddr; break;
+                    case Location::Stack:
+                        std::cerr << "SP" << loc.stackoffs; break;
+                }
+                std::cerr << "]";
+            }
+            std::cerr << std::endl;
+        }
+        
+        void RequireST(int stno)
+        {
+            // Generates the necessary statements to ensure
+            // that stack[last-stno] is ST(stno).
+            size_t lastitem = stack.size()-1 - stno;
+            MoveToST(stack[lastitem], stno);
+        }
+        int RequireXMM(int top_offs)
+        {
+            // Generates the necessary statements to ensure
+            // that stack[0] is in an XMM register
+            Location& top = stack[stack.size()-1 - top_offs];
+            if(top.Loc != Location::XMM)
+            {
+                int xmm = GetFreeXMM();
+                MoveToXMM(top, xmm);
+            }
+            return top.xmm_no;
+        }
+        void RoomST(int n) // Ensures there's room for at least n items of growth in ST
+        {
+            while(fpu_stack_depth+n > 8)
+            {
+                Spill(FindST(fpu_stack_depth-1));
+            }
+        }
+        Location& FindST(int stno)
+        {
+            for(size_t a=0; a<stack.size(); ++a)
+                if(stack[a].Loc == Location::ST
+                && stack[a].st_no == stno)
+                    return stack[a];
+            static Location dummy;
+            return dummy;
+        }
+        void GotST() // Informs that we've got a new value in st0
+        {
+            SimuSTpop(1);
+            Location loc;
+            loc.Loc   = Location::ST;
+            loc.st_no = 0;
+            stack.push_back(loc);
+        }
+        void GotXMM(int xmm)
+        {
+            Location loc;
+            loc.Loc    = Location::XMM;
+            loc.xmm_no = xmm;
+            stack.push_back(loc);
+        }
+        void SimuSTpop(int offset = -1)
+        {
+            // assumes that ST0 was just removed from stack
+            for(size_t a=0; a<stack.size(); ++a)
+                if(stack[a].Loc == Location::ST)
+                    stack[a].st_no += offset;
+            fpu_stack_depth += offset;
+        }
+        void DidPop()
+        {
+            Location& top = stack[stack.size()-1];
+            bool WasST0 = top.Loc == Location::ST && top.st_no == 0;
+            stack.erase(stack.begin() + stack.size() - 1);
+            if(WasST0) SimuSTpop();
+        }
+        int GetFreeXMM()
+        {
+        #ifdef __x86_64
+            const int max_xmm = 16;
+        #else
+            const int max_xmm = 8;
+        #endif
+            bool XMM_Use[max_xmm] = {false};
+            for(size_t a=0; a<stack.size(); ++a)
+                if(stack[a].Loc == Location::XMM)
+                    XMM_Use[stack[a].xmm_no] = true;
+            for(int n=0; n<max_xmm; ++n)
+            {
+                if(!XMM_Use[n]) return n;
+            }
+            /* Spill one XMM register */
+            for(size_t a=0; a<stack.size(); ++a)
+                if(stack[a].Loc == Location::XMM)
+                {
+                    int xmm  = stack[a].xmm_no;
+                    Spill(stack[a]);
+                    return xmm;
+                }
+            /* Eh, what's the XMM registers being used for then?? */
+            return -1;
+        }
+        void Spill(Location& loc)
+        {
+            switch(loc.Loc)
+            {
+                case Location::XMM:
+                {
+                    int xmm  = loc.xmm_no;
+                    int slot = AllocStackSlot();
+                    loc.Loc       = Location::Stack;
+                    loc.stackoffs = slot;
+                    SynthXMM_Stack(0xF2, (xmm&8)?0x44:0, 0x0F,0x11,(xmm&7)*8, slot);
+                    break;
+                }
+                case Location::ST:
+                {
+                    int st   = loc.st_no;
+                    int slot = AllocStackSlot();
+                    loc.Loc       = Location::Stack;
+                    loc.stackoffs = slot;
+                    
+                    if(st == 7)
+                    {
+                        // spilling ST(7) is easy. Just fld st(7), and store it.
+                        SynthST_Stno(0xD9, 0xC0, st); // fld st7
+                        SynthST_Stack(0xDD,0x18, loc.stackoffs); // fstp addr
+                        // no renumbering needed.
+                        --fpu_stack_depth;
+                    }
+                    else
+                    {
+                        if(st != 0)
+                        {
+                            // Make it st0 by swapping it with whatever _is_ st0
+                            SynthST_Stno(0xD9, 0xC8, st); // fxch st#
+                            // Now it is st0.
+                            // But st0 is now st, so we have to update it to reflect the fact                        
+                            FindST(0).st_no = st;
+                        }
+                        SynthST_Stack(0xDD,0x18, loc.stackoffs); // fstp addr
+                        SimuSTpop(); // renumber each ST address.
+                    }
+                    break;
+                }
+                case Location::Mem:
+                case Location::Stack:
+                    break; // don't need spilling
+            }
+        }
+        Location CopyToXMM(Location& loc, int xmm, bool move = false)
+        {
+        retry:
+            switch(loc.Loc)
+            {
+                case Location::XMM:
+                    if(loc.xmm_no != xmm)
+                        SynthXMM_XMM(0xF2, 0x0F,0x10, xmm, loc.xmm_no);
+                    break;
+                case Location::ST:
+                    Spill(loc);
+                    goto retry;
+                case Location::Mem:
+                {
+                    SynthXMM_Mem(0xF2, (xmm&8)?0x44:0, 0x0F,0x10,(xmm&7)*8, loc.memaddr, loc.expected_reuse);
+                    break;
+                }
+                case Location::Stack:
+                    SynthXMM_Stack(0xF2, (xmm&8)?0x44:0, 0x0F,0x10,(xmm&7)*8, loc.stackoffs);
+                    if(move) Stack_Use.erase(loc.stackoffs);
+                    break;
+            }
+            
+            Location res;
+            res.Loc    = Location::XMM;
+            res.xmm_no = xmm;
+            
+            if(move) loc = res;
+            
+            return res;
+        }
+        void MoveToXMM(Location& loc, int xmm)
+        {
+            CopyToXMM(loc, xmm, true);
+        }
+        
+        void MoveToST(Location& loc, int stno)
+        {
+        retry:
+            switch(loc.Loc)
+            {
+                case Location::XMM:
+                    Spill(loc);
+                    goto retry;
+                case Location::ST:
+                    if(loc.st_no != stno)
+                    {
+                        SynthST_Stno(0xD9, 0xC8, loc.st_no); // fxch st#
+                        // Whatever _was_ 0, change it to indicate where it's now
+                        FindST(0).st_no = loc.st_no;
+                        if(stno != 0)
+                        {
+                            SynthST_Stno(0xD9, 0xC8, stno); // fxch st#
+                            // Whatever _was_ stno, change it to indicate that it's at 0 now
+                            FindST(stno).st_no = 0;
+                        }
+                    }
+                    break;
+                case Location::Mem:
+                {
+                    RoomST(1);
+                    if(loc.Loc != Location::Mem) goto retry;
+                    SynthST_Mem(0xDD, 0x00, loc.memaddr, loc.expected_reuse); // fld qword [...]
+                    SimuSTpop(1);
+                    break;
+                }
+                case Location::Stack:
+                    RoomST(1);
+                    if(loc.Loc != Location::Stack) goto retry;
+                    SynthST_Stack(0xDD, 0x00, loc.stackoffs); // fld qword [...]
+                    SimuSTpop(1);
+                    Stack_Use.erase(loc.stackoffs);
+                    break;
+            }
+            loc.Loc    = Location::ST;
+            loc.st_no  = stno;
+        }
+        int AllocStackSlot()
+        {
+            int n=0;
+            while(Stack_Use.find(n) != Stack_Use.end()) n -= 8;
+            Stack_Use.insert(n);
+            return n;
+        }       
+        
+        void PullResult()
+        {
+            Location& loc = stack[stack.size()-1];
+        #ifdef __x86_64
+            /* Must transfer the value to xmm0 at end */
+            MoveToXMM(loc, 0);
+        #endif
+        #ifndef __x86_64
+            /* Must transfer the value to st0 at end */
+            MoveToST(loc, 0);
+        #endif
+        }
+        
+        void SynthXMM_XMM(int prefix, int b1, int b2, int reg1, int reg2)
+        {
+            if(prefix) com.Synth(prefix);
+            if(reg2 & 8)
+                com.Synth( (reg1 & 8) ? 0x45 : 0x41);
+            else if(reg1 & 8)
+                com.Synth(0x44);
+            com.Synth(b1, b2, 0xC0 + (reg1&7)*8 + (reg2&7));
+        }
+        void SynthXMM_Mem(int prefix, int code64, int b1, int b2, int b3, const void* addr, bool expected_reuse)
+        {
+            int basereg = SynthLoadAddr(addr, expected_reuse);
+            com.Synth(prefix);
+            if(basereg&8) code64 |= 0x41;
+            if(code64) com.Synth(code64);
+            com.Synth(b1, b2, b3 + (basereg&7));
+        }
+        void SynthXMM_Stack(int prefix, int code64, int b1, int b2, int b3, int stackoffs)
+        {
+            com.Synth(prefix);
+            if(code64) com.Synth(code64);
+            com.Synth(b1, b2);
+            SynthStackSIB(b3, stackoffs);
+        }
+        void SynthST_Mem(int b1,int b2, const void* addr, bool expected_reuse)
+        {
+            int basereg = SynthLoadAddr(addr, expected_reuse);
+            if(basereg&8) com.Synth(0x41);
+            com.Synth(b1, b2 + basereg);
+        }
+        void SynthST_Stno(int b1,int b2, int stno)
+        {
+            com.Synth(b1, (0xC0|b2) + stno);
+        }
+        void SynthST_Stack(int b1,int b2, int stackoffs)
+        {
+            com.Synth(b1);
+            SynthStackSIB(b2, stackoffs);
+        }
+        void SynthStackSIB(int b3,int stackoffs)
+        {
+            if(!stackoffs)
+                { com.Synth(b3 + 0x04, 0x24); }
+            else if(stackoffs >= -128 && stackoffs < 128)
+                { com.Synth(b3 + 0x44, 0x24); com.Synth( (int_least8_t) stackoffs ); }
+            else
+                { com.Synth(b3 + 0x84, 0x24); com.SynthI32( (int_least32_t) stackoffs ); }
+        }
+        int SynthLoadAddr(const void* addr, bool expected_reuse)
+        {
+            int basereg = 0, freereg = 0;
+            #ifdef __x86_64
+            int num_registers = 16;
+            #else
+            int num_registers = 8;
+            #endif
+            
+            if(!expected_reuse)
+                num_registers = 2; // eax or ecx for temporaries.
+            
+            for(basereg=num_registers; basereg-->0; )
+            {
+                // Registers ebx, ebp, r12, r13, r14 and r15 belong to the calling function
+                // We can't clobber them.
+                if(basereg == 3
+                || basereg == 5
+                || (basereg >= 12 && basereg <= 15)) continue;
+                // Register esp cannot be used
+                if(basereg == 4) continue;
+                if(expected_reuse && basereg<2) continue;
+                
+                if(basereg_use[basereg] == addr) return basereg;
+                if(!basereg_use[basereg]) freereg = basereg;
+            }
+            basereg_use[basereg = freereg] = addr;
+            SynthLoadAddr(addr, basereg);
+            return basereg;
+        }
+        void SynthLoadAddr(const void* addr, int basereg)
+        {
+        #ifdef __x86_64
+            com.Synth((basereg&8) ? 0x49 : 0x48, 0xB8 + (basereg&7) );
+            com.SynthI64( (uint_fast64_t) addr);  // mov rax, qword ptr value
+        #else
+            com.Synth(0xB8+basereg);
+            com.SynthI32( (uint_fast32_t) addr);  // mov eax, dword ptr value
+        #endif
+        }
+    };
 
-
-    void SynthesizeCode_SimpleFP(
+    void SynthesizeCode_Generic(
         const opcode* const op_begin,
         const opcode* const op_end,
+        CodeSynth& synth,
         size_t ImmedPtr = 0,
         bool DoEntryExit = true)
     {
@@ -94,72 +737,48 @@
                 switch(*op++)
                 {
                     case opVar: ++op; break;
-                    
-                    case opExp:
-                        // I386:   Requires 1 value for parameter
-                        // X86_64: Requires 1 storage for moving between st(0) and xmm0
-                        //         But such storage does not need to be explicitly allocated
-                      #ifndef __x86_64
-                        stack_required = std::max(stack_required, (size_t)1);
-                      #endif
-                        break;
-                    case opPow:
-                        // I386:   Requires 2 values for parameter
-                        // X86_64: Requires 1 storage for moving between st(0) and xmm0
-                        //         But such storage does not need to be explicitly allocated
-                      #ifdef __x86_64
-                        stack_required = std::max(stack_required, (size_t)2);
-                      #endif
-                        break;
                     default: ;
                 }
+            #ifdef __x86_64
+            // 1 stack slot is required at end for converting to sse
+            stack_required = std::max(stack_required, (size_t)1);
+            #endif
             
             /* If this function requires a stack, allocate it */
             if(stack_required)
-            {
-                stack_required = (stack_required + 1) * 8;
-                
-                #ifdef __x86_64
-                    Synth(0x48, 0x81, 0xEC);
-                    SynthI32(stack_required);  // sub rsp, n*8
-                #else
-                    stack_required += 4; // improve aligning a bit                
-                    Synth(0x81, 0xEC);
-                    SynthI32(stack_required);  // sub esp, n*8
-                #endif
-            }
+                stack_required = SynthStackBegin(stack_required);
         }
         
         for(const opcode* op = op_begin; op < op_end; )
             switch(*op++)
             {
-                case opPlus:  Synth(0xDE, 0xC1); break; // faddp st(1)
-                case opMinus: Synth(0xDE, 0xE9); break; // fsubp st(1)
-                case opMul:   Synth(0xDE, 0xC9); break; // fmulp st(1)
-                case opDiv:   Synth(0xDE, 0xF9); break; // fdivp st(1)
+                case opPlus:  synth.GenAdd(false); break; // faddp st(1)
+                case opMinus: synth.GenSub(false); break; // fsubp st(1)
+                case opMul:   synth.GenMul(false); break; // fmulp st(1)
+                case opDiv:   synth.GenDiv(false); break; // fdivp st(1)
                 case opDup:
                     if(*op == opMul) // opDup,opMul  x*x idiom?
                     {
                         // do a fmul without involving the stack
                         ++op;
-                        Synth(0xD8, 0xC8); // fmul st0
+                        synth.GenMul(true);
                     }
                     else if(*op == opPlus) // opDup,opPlus  x+x idiom?
                     {
                         // do a fadd without involving the stack
                         ++op;
-                        Synth(0xD8, 0xC0); // fadd st0
+                        synth.GenAdd(true);
                     }
                     else
                     {
-                        Synth(0xD9, 0xC0); // fld st(0)
+                        synth.GenDup();
                     }
                     break;
-                case opNeg:   Synth(0xD9, 0xE0); break; // fchs
-                case opSqrt:  Synth(0xD9, 0xFA); break; // fsqrt
-                case opSin:   Synth(0xD9, 0xFE); break; // fsin
-                case opCos:   Synth(0xD9, 0xFF); break; // fcos
-                case opExp:   
+                case opNeg:   synth.GenNeg(); break;
+                case opSqrt:  synth.GenSqrt(); break;
+                case opSin:   synth.RequireST(0); Synth(0xD9, 0xFE); break; // fsin
+                case opCos:   synth.RequireST(0); Synth(0xD9, 0xFF); break; // fcos
+                case opExp:
                 {
                     /* There is no natural exponent opcode on 387.
                        To perform this operation, we would need
@@ -191,6 +810,8 @@
                        with register saving and all, we have no choice.
                      */
                     
+                    synth.RequireST(0);
+                    synth.RoomST(1);
                     Synth(0xD9, 0xEA); // fld2e
                     Synth(0xDE, 0xC9); // fmulp st1
                     Synth(0xD9, 0xC0); // fld st0
@@ -222,6 +843,9 @@
                        For this, we use the same trick as above
                        in exp().
                      */
+                    synth.RequireST(1);
+                    synth.RequireST(0);
+                    synth.RoomST(1);
                     Synth(0xD9, 0xF1); // fyl2x: log2(a)*b
                     Synth(0xD9, 0xC0); // fld st0
                     Synth(0xD9, 0xFC); // frndint
@@ -232,6 +856,7 @@
                     Synth(0xDE, 0xC1); // faddp  st1
                     Synth(0xD9, 0xFD); // fscale
                     Synth(0xDD, 0xD9); // fstp st1
+                    synth.DidPop();
                     break;
                 }
 
@@ -244,7 +869,7 @@
                         /* Check for special cases of integer exponents */
                         for(int sqrtcount=0; sqrtcount < 30; ++sqrtcount)
                         {
-                            const double immed_effected = immed / (1 << sqrtcount);
+                            const double immed_effected = immed * (1 << sqrtcount);
                             if( (int)immed_effected == immed_effected)
                             {
                                 int power = (int)immed_effected;
@@ -282,24 +907,24 @@
                                 while(power > 1)
                                 {
                                     if(power & 1)
-                                        { Synth(0xD9, 0xC0); // fld self
+                                        { synth.GenDup(); //  make dup
                                           --power;
                                           ++n_backups;
                                           continue;
                                         }
-                                    Synth(0xD8, 0xC8); // fmul itself
+                                    synth.GenMul(true); // mul self
                                     power /= 2;
                                 }
                                 for(; n_backups > 0; --n_backups)
-                                    Synth(0xDE, 0xC9); // fmul backup and pop it
+                                    synth.GenMul(false); // mul and pop
 
                                 if(immed < 0) // negative exponents are 1/x
                                 {
-                                    Synth(0xD9, 0xE8); // fld1
-                                    Synth(0xDE, 0xF1); // fdivrp st1
+                                    synth.GenConstLoad(FP_Constant_One);
+                                    synth.GenRDiv(false);
                                 }
                                 for(; sqrtcount > 0; --sqrtcount)
-                                    Synth(0xD9, 0xFA); // fsqrt
+                                    synth.GenSqrt();
                                 
                                 ++op; // skip pow
                                 goto DoneImmed;
@@ -307,59 +932,15 @@
                         }
                     }
                     
-                    if(immed == 1.0)
-                        Synth(0xD9, 0xE8); // fld1
-                    else if(immed == 3.3219280948873623478)
-                        Synth(0xD9, 0xE9); // log2(10)
-                    else if(immed == 1.4426950408889634074)
-                        Synth(0xD9, 0xEA); // log2(e)
-                    else if(immed == 3.14159265358979323846)
-                        Synth(0xD9, 0xEB); // fldpi
-                    else if(immed == 0.86858896380650365529)
-                        Synth(0xD9, 0xEC); // log10(2)
-                    else if(immed == 0.69314718055994530943)
-                        Synth(0xD9, 0xED); // loge(2)
-                    else if(immed == 0.0)
-                        Synth(0xD9, 0xEE); // fldz
-                    else
-                    {
-                    #ifdef __x86_64
-                        Synth(0x48, 0xB8);
-                        SynthI64( (uint_fast64_t) &immed);  // mov rax, qword ptr immed
-                    #else
-                        Synth(0xB8);
-                        SynthI32( (uint_fast32_t) &immed);  // mov eax, dword ptr immed
-                    #endif
-                        goto ImmedLoad;
-                    }
+                    synth.GenConstLoad(immed);
                 DoneImmed:
                     break;
                 }
                 
                 case opVar:
                 {
-                  {
                     double& var = vars[ (size_t) *op++ ];
-                #ifdef __x86_64
-                    Synth(0x48, 0xB8);
-                    SynthI64( (uint_fast64_t) &var);    // mov rax, qword ptr var
-                #else
-                    Synth(0xB8);
-                    SynthI32( (uint_fast32_t) &var);    // mov eax, dword ptr var
-                #endif
-                  }
-                ImmedLoad:
-                    switch(*op)
-                    {
-                      /* -- broken?
-                        case opPlus:  Synth(0xDC,0x00); break; // fadd qword[eax]
-                        case opMinus: Synth(0xDC,0x20); break; // fsub qword[eax]
-                        case opMul:   Synth(0xDC,0x08); break; // fmul qword[eax]
-                        case opDiv:   Synth(0xDC,0x30); break; // fdiv qword[eax]
-                      */
-                        default:
-                            Synth(0xDD, 0x00); // fld qword [eax]
-                    }
+                    synth.GenVarLoad(var);
                     break;
                 }
             }
@@ -376,159 +957,10 @@
         {
             /* If this function required a stack, deallocate it */
             if(stack_required)
-            {
-                #ifdef __x86_64
-                    Synth(0x48, 0x81, 0xC4);
-                    SynthI32(stack_required);  // add rsp, n*8
-                #else
-                    Synth(0x81, 0xC4);
-                    SynthI32(stack_required);  // add esp, n*8
-                #endif
-            }
-        #ifdef __x86_64
-            /* Must transfer the value to xmm0 at end */
-            Synth(0xDD,0x5C,0x24,0xF8);           // fstp qword[rsp-8]
-            Synth(0xF2,0x0F,0x10,0x44,0x24,0xF8); // movsd xmm0, [rsp-8]
-        #endif
-            Synth(0xC3); // ret
-        }
-    }
-    
-    void SynthesizeCode_SimpleSSE(
-        const opcode* const op_begin,
-        const opcode* const op_end,
-        int StackRegisters[16],
-        size_t ImmedPtr = 0,
-        bool DoEntryExit = true)
-    {
-        int StackPtr = 0;    
-    
-        #define EmptyCheck() do { \
-            if(StackPtr < 0) { std::cerr << "Stack empty?\n"; return; } \
-        } while(0)
-    #ifdef x86_64
-        #define FullCheck() do { \
-            if(StackPtr >= 16) { std::cerr << "Stack full?\n"; return; } \
-        } while(0)
-    #else
-        /* 32-bit has only 8 xmm registers */
-        #define FullCheck() do { \
-            if(StackPtr >= 8) { std::cerr << "Stack full?\n"; return; } \
-        } while(0)
-    #endif
-
-        #define Pop() StackRegisters[({ EmptyCheck();}), --StackPtr]
-        #define Push() StackRegisters[({ FullCheck();}), StackPtr++]
-        #define Top() StackRegisters[({EmptyCheck();}), StackPtr-1]
-        
-        #define SSEsynth2(byte2, curs, tops) do { \
-            int cur = (curs), top = (tops); \
-            Synth(0xF2); \
-            if(top&8) \
-                Synth( (cur&8) ? 0x45 : 0x41); \
-            else if(cur & 8) \
-                Synth(0x44); \
-            Synth(0x0F, byte2, 0xC0 + (top&7) + (cur&7)*8); \
-        } while(0)
-        
-        
-        /* UNDER CONSTRUCTION */
-        
-        for(const opcode* op = op_begin; op < op_end; )
-            switch(*op++)
-            {
-                case opPlus:  { int t = Pop(); SSEsynth2(0x58, Top(), t); break; } // addsd top, pop
-                case opMinus: { int t = Pop(); SSEsynth2(0x5C, Top(), t); break; } // subsd top, pop
-                case opMul:   { int t = Pop(); SSEsynth2(0x59, Top(), t); break; } // mulsd top, pop
-                case opDiv:   { int t = Pop(); SSEsynth2(0x5E, Top(), t); break; } // divsd top, pop
-                case opDup:   { int t = Top(); SSEsynth2(0x10, Push(), t); break; } // movsd push, top
-                case opNeg:
-                {
-                    int t = Top();
-                #ifdef __x86_64
-                    Synth(0x48, 0xB8);
-                    SynthI64( (uint_fast64_t) &SSE_NegPattern);    // mov rax, qword ptr var
-                #else
-                    Synth(0xB8);
-                    SynthI32( (uint_fast32_t) &SSE_NegPattern);    // mov eax, dword ptr var
-                #endif
-                    Synth(0x66);
-                    if(t&8) Synth(0x44);
-                    Synth(0x0F, 0x57, 0x00); // xorpd xmm, [rax]
-                    break;
-                }
-                case opSqrt:  { int t = Pop(); SSEsynth2(0x51, Top(), t); break; } // sqrtsd top, pop
-                case opSin:
-                {
-                    // Should do a function call here...
-                    // But eh, which registers we should save? This will be a lot of problem.
-                #ifdef x86_64
-                #else
-                #endif
-                    // NOT IMPLEMENTED
-                    break;
-                }
-                case opCos:
-                {
-                    // NOT IMPLEMENTED
-                    break;
-                }
-                case opExp:
-                {
-                    // NOT IMPLEMENTED
-                    break;
-                }
-                case opPow:
-                {
-                    // NOT IMPLEMENTED
-                    break;
-                }
-
-                case opImmed: 
-                {
-                    int t = Push();
-                    const double& immed = immeds[ImmedPtr++];
-                #ifdef __x86_64
-                    Synth(0x48, 0xB8);
-                    SynthI64( (uint_fast64_t) &immed);    // mov rax, qword ptr immed
-                #else
-                    Synth(0xB8);
-                    SynthI32( (uint_fast32_t) &immed);    // mov eax, dword ptr immed
-                #endif
-                    Synth(0xF2);
-                    if(t&8) Synth(0x44);
-                    Synth(0x10, 0x00); // movsd xmm, qword [eax]
-                    break;
-                }
-                
-                case opVar:
-                {
-                    int t = Push();
-                    double& var = vars[ (size_t) *op++ ];
-                #ifdef __x86_64
-                    Synth(0x48, 0xB8);
-                    SynthI64( (uint_fast64_t) &var);    // mov rax, qword ptr var
-                #else
-                    Synth(0xB8);
-                    SynthI32( (uint_fast32_t) &var);    // mov eax, dword ptr var
-                #endif
-                    Synth(0xF2);
-                    if(t&8) Synth(0x44);
-                    Synth(0x10, 0x00); // movsd xmm, qword [eax]
-                    break;
-                }
-            }
-            
-        if(DoEntryExit)
-        {
+                SynthStackEnd(stack_required);
+            synth.PullResult();
             Synth(0xC3); // ret
         }
-
-        #undef FullCheck
-        #undef EmptyCheck
-        #undef Push
-        #undef Top
-        #undef Pop
     }
     
     inline void Synth(unsigned char c) { CodeBuffer.push_back(c); }
@@ -560,6 +992,7 @@
 
 private:
     std::vector<unsigned char> CodeBuffer;
+    const char* name;
     unsigned char* Code;
     unsigned char* CodePtr;
 };
diff -NaHudr fparser-jittest-1.1/jittest.cc fparser-jittest-1.2/jittest.cc
--- fparser-jittest-1.1/jittest.cc	2008-01-10 18:27:46.000000000 +0200
+++ fparser-jittest-1.2/jittest.cc	2008-01-10 20:08:18.000000000 +0200
@@ -16,11 +16,8 @@
     double& x = vars[0];
     double& y = vars[1];
     return
-std::exp((-x*x-y*y)/100.0)*std::sin(std::sqrt(x*x+y*y))
-      /(10*2)
-    
+std::exp((-x*x-y*y)/100.0)*std::sin(std::sqrt(x*x+y*y)) /(10*2)
      + std::sin(std::pow(x,4)-4*std::pow(x,3)+3*std::pow(x,2)-2*x+2*5-3)
-
      - std::cos(-2*std::pow(y,4)+5*std::pow(y,3)-14*std::pow(x,2)+8*x-120/2.0+4)
     ;
 }
@@ -55,14 +52,17 @@
     }
 endtest:
     std::cout << " EvalTime(" << (4000.0/counter) << " us.)"
-              << " Speed(" << (1000.0*counter/4) << " loops/sec)"
+              << " Speed(" << (long)(1000.0*counter/4) << " loops/sec)"
               << std::endl;
 }
 
 int main()
 {
-    Compiler c(opcodes, sizeof(opcodes)/sizeof(*opcodes));
-    DoTimingTests(c);
+    Compiler c_sse(opcodes, sizeof(opcodes)/sizeof(*opcodes), true);
+    DoTimingTests(c_sse);
+    
+    Compiler c_fp(opcodes, sizeof(opcodes)/sizeof(*opcodes), false);
+    DoTimingTests(c_fp);
 
     Interpreter i(opcodes, sizeof(opcodes)/sizeof(*opcodes));
     DoTimingTests(i);
