/*
    JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine
    Release Version 2.0

    A project from the Physics Dept, The University of Oxford

    Copyright (C) 2007 Isis Innovation Limited

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2 as published by
    the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
    Details (including contact information) can be found at: 

    www.physics.ox.ac.uk/jpc
*/

package org.jpc.sourcecompiler;

import java.lang.reflect.*;
import org.jpc.emulator.memory.codeblock.optimised.*;

abstract class MicrocodeSetSource
{
    static String[][] IBMSource;

    protected static char[][] makeSourceArray(Class microcodeSet, Class sourceSet)
    {
        Field[] fields1 = microcodeSet.getDeclaredFields();
        Field[] fields2 = sourceSet.getDeclaredFields();
        int microcode;
        char[][] microcodeMethods = new char[fields1.length][];   
        int[] IBMicrocodes = new int[0];
         
        //construct array of strings corresponding to code for each microcode
        for (int i =0; i< fields1.length; i++)
        {
            //check if microcode is an immediate byte microcode and if so add it to the list
            try
            {
                if (fields1[i].getName().endsWith("IB") || fields1[i].getName().endsWith("IW") || fields1[i].getName().endsWith("ID"))
                {
                    int[] temp = new int[IBMicrocodes.length + 1];
                    System.arraycopy(IBMicrocodes, 0, temp, 0, IBMicrocodes.length);
                    temp[temp.length - 1] = fields1[i].getInt(fields1[i]);
                    IBMicrocodes = temp;
                }
            }
            catch (Exception e) {}
          
            for (int j = 0; j< fields2.length; j++)
            {
                if (fields1[i].getName().compareTo(fields2[j].getName()) == 0)
                {
                    try
                    {
                        microcode = fields1[i].getInt(fields1[i]);
                        microcodeMethods[microcode] = ((String) fields2[j].get(fields2[j])).toCharArray();
                    }
                    catch (Exception e) {}
                }
            }
        }
        return microcodeMethods;
    }

    protected static int[] findIBMicrocodes(Class microcodeSet, Class sourceSet)
    {
        Field[] fields1 = microcodeSet.getDeclaredFields();
        Field[] fields2 = sourceSet.getDeclaredFields();
        int[] IBMicrocodes = new int[0];
        IBMSource = new String[fields1.length][2];
         
        for (int i =0; i< fields1.length; i++)
        {
            //check if microcode is an immediate byte microcode and if so add it to the list
            try
            {
                boolean split = false;
                if ((fields1[i].getName().compareTo("POP_O16_A16")==0) || (fields1[i].getName().compareTo("POP_O32_A16")==0))
                {
                    split = true;
                }

                if (fields1[i].getName().endsWith("_IB") || fields1[i].getName().endsWith("_IW") || fields1[i].getName().endsWith("_ID") || split)
                {
                    if (!split)
                    {
                        int[] temp = new int[IBMicrocodes.length + 1];
                        System.arraycopy(IBMicrocodes, 0, temp, 0, IBMicrocodes.length);
                        temp[temp.length - 1] = fields1[i].getInt(fields1[i]);
                        IBMicrocodes = temp;
                    }

                    //add source for IB Microcode to IBMSource
                    for (int j = 0; j< fields2.length; j++) // i know this is innefficient
                    {
                        if (fields1[i].getName().compareTo(fields2[j].getName()) == 0)
                        {
                            try
                            {
                                int microcode = fields1[i].getInt(fields1[i]);
                                String code = (String) fields2[j].get(fields2[j]);
                                if (split)
                                {
                                    int start = code.indexOf("microcodes[position] == STORE0_SS");
                                    //add string before microcodes reference
                                    IBMSource[microcode][0] = code.substring(0,start);
                                    //add string after microcodes reference
                                    IBMSource[microcode][1] = code.substring(start + 33, code.length()) + "\n";
                                    break;
                                }
                                int start = code.indexOf("microcodes[position++]");
                                //add string before microcodes reference
                                IBMSource[microcode][0] = code.substring(0,start);
                                //add string after microcodes reference
                                IBMSource[microcode][1] = code.substring(start + 22, code.length()) + "\n";
                                break;
                            }
                            catch (Exception e) {e.printStackTrace();}
                        }
                    }
                }
            }
            catch (Exception e) {}
        }
        return IBMicrocodes;
    }
}
