dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnet/engine md_arm.h,NONE,1.1 md_default.h,N


From: Rhys Weatherley <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnet/engine md_arm.h,NONE,1.1 md_default.h,NONE,1.1 md_x86.h,NONE,1.1 unroll.c,NONE,1.1 unroll_var.c,NONE,1.1
Date: Wed, 14 May 2003 02:17:14 -0400

Update of /cvsroot/dotgnu-pnet/pnet/engine
In directory subversions:/tmp/cvs-serv12824/engine

Added Files:
        md_arm.h md_default.h md_x86.h unroll.c unroll_var.c 
Log Message:


Check in some of the generic unroller code (it isn't working yet).


--- NEW FILE ---
/*
 * md_arm.h - Machine-dependent definitions for ARM.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _ENGINE_MD_ARM_H
#define _ENGINE_MD_ARM_H

#include "arm_codegen.h"

#ifdef  __cplusplus
extern  "C" {
#endif

/*
 * Register numbers in the standard register allocation order.
 * -1 is the list terminator.
 */
#define MD_REG_0                ARM_R0
#define MD_REG_1                ARM_R1
#define MD_REG_2                ARM_R2
#define MD_REG_3                ARM_R3
#define MD_REG_4                ARM_R4
#define MD_REG_5                ARM_R7
#define MD_REG_6                ARM_R8
#define MD_REG_7                ARM_R9
#define MD_REG_8                -1
#define MD_REG_9                -1
#define MD_REG_10               -1
#define MD_REG_11               -1
#define MD_REG_12               -1
#define MD_REG_13               -1
#define MD_REG_14               -1
#define MD_REG_15               -1

/*
 * Mask that indicates a floating-point register.
 */
#define MD_FREG_MASK    0x0010

/*
 * Floating point register numbers in the standard allocation order.
 * -1 is the list terminator.  The floating point register numbers
 * must include the MD_FREG_MASK value.
 */
#define MD_FREG_0               -1
#define MD_FREG_1               -1
#define MD_FREG_2               -1
#define MD_FREG_3               -1
#define MD_FREG_4               -1
#define MD_FREG_5               -1
#define MD_FREG_6               -1
#define MD_FREG_7               -1
#define MD_FREG_8               -1
#define MD_FREG_9               -1
#define MD_FREG_10              -1
#define MD_FREG_11              -1
#define MD_FREG_12              -1
#define MD_FREG_13              -1
#define MD_FREG_14              -1
#define MD_FREG_15              -1

/*
 * Set this to a non-zero value if floating-point registers are organised
 * in a stack (e.g. the x87 FPU).
 */
#define MD_FP_STACK_SIZE        0

/*
 * The register that contains the CVM program counter.  This may be
 * present in the standard register allocation order.  This can be
 * set to -1 if MD_STATE_ALREADY_IN_REGS is 0.
 */
#define MD_REG_PC               ARM_R4

/*
 * The register that contains the CVM stacktop pointer.  This must not
 * be present in the standard register allocation order.
 */
#define MD_REG_STACK    ARM_R5

/*
 * The register that contains the CVM frame pointer.  This must not
 * be present in the standard register allocation order.
 */
#define MD_REG_FRAME    ARM_R6

/*
 * Set this to 1 if "pc", "stacktop", and "frame" are already in
 * the above registers when unrolled code is entered.  i.e. the
 * CVM interpreter has manual assignments of registers to variables
 * in the file "cvm.c".  If the state is not already in registers,
 * then set this value to zero.
 */
#define MD_STATE_ALREADY_IN_REGS        1

/*
 * Registers that must be saved on the system stack prior to their use
 * in unrolled code for temporary stack values.
 */
#define MD_REGS_TO_BE_SAVED     \
                        ((1 << ARM_R7) | (1 << ARM_R8) | (1 << ARM_R9))

/*
 * Registers with special meanings (pc, stacktop, frame) that must
 * be saved if MD_STATE_ALREADY_IN_REGS is 0.
 */
#define MD_SPECIAL_REGS_TO_BE_SAVED     0

/*
 * Set this to 1 if the CPU has integer division operations.
 * Set it to zero if integer division is too hard to be performed
 * inline using a simple opcode.
 */
#define MD_HAS_INT_DIVISION                     0

/*
 * Type of the instruction pointer for outputting code.
 */
typedef arm_inst_ptr    md_inst_ptr;

/*
 * Push a word register onto the system stack.
 */
#define md_push_reg(inst,reg)   arm_push_reg((inst), (reg))

/*
 * Pop a word register from the system stack.
 */
#define md_pop_reg(inst,reg)    arm_pop_reg((inst), (reg))

/*
 * Discard the contents of a floating-point register.
 */
#define md_discard_freg(inst,reg)       do { ; } while (0)

/*
 * Load a 32-bit integer constant into a register.  This will sign-extend
 * if the native word size is larger.
 */
#define md_load_const_32(inst,reg,value)        \
                        arm_mov_reg_imm((inst), (reg), (value))

/*
 * Load a native integer constant into a register.
 */
#define md_load_const_native(inst,reg,value)    \
                        arm_mov_reg_imm((inst), (reg), (value))

/*
 * Load a 32-bit word register from an offset from a pointer register.
 * This will sign-extend if the native word size is larger.
 */
#define md_load_membase_word_32(inst,reg,basereg,offset)        \
                        arm_load_membase((inst), (reg), (basereg), (offset))

/*
 * Load a native-sized word register from an offset from a pointer register.
 */
#define md_load_membase_word_native(inst,reg,basereg,offset)    \
                        arm_load_membase((inst), (reg), (basereg), (offset))

/*
 * Load a byte value from an offset from a pointer register.
 */
#define md_load_membase_byte(inst,reg,basereg,offset)   \
                        arm_load_membase_byte((inst), (reg), (basereg), 
(offset))

/*
 * Load a signed byte value from an offset from a pointer register.
 */
#define md_load_membase_sbyte(inst,reg,basereg,offset)  \
                        arm_load_membase_sbyte((inst), (reg), (basereg), 
(offset))

/*
 * Load a short value from an offset from a pointer register.
 */
#define md_load_membase_short(inst,reg,basereg,offset)  \
                        arm_load_membase_short((inst), (reg), (basereg), 
(offset))

/*
 * Load an unsigned short value from an offset from a pointer register.
 */
#define md_load_membase_ushort(inst,reg,basereg,offset) \
                        arm_load_membase_ushort((inst), (reg), (basereg), 
(offset))

/*
 * Load a floating-point value from an offset from a pointer register.
 * If the system uses floating-point registers, then the value is
 * loaded into "reg".  Otherwise it is loaded onto the top of the
 * floating-point stack.
 */
#define md_load_membase_float_32(inst,reg,basereg,offset)       \
                        do { ; } while (0)
#define md_load_membase_float_64(inst,reg,basereg,offset)       \
                        do { ; } while (0)
#define md_load_membase_float_native(inst,reg,basereg,offset)   \
                        do { ; } while (0)

/*
 * Store a 32-bit word register to an offset from a pointer register.
 */
#define md_store_membase_word_32(inst,reg,basereg,offset)       \
                        arm_store_membase((inst), (reg), (basereg), (offset))

/*
 * Store a native-sized word register to an offset from a pointer register.
 */
#define md_store_membase_word_native(inst,reg,basereg,offset)   \
                        arm_store_membase((inst), (reg), (basereg), (offset))

/*
 * Store a byte value to an offset from a pointer register.
 */
#define md_store_membase_byte(inst,reg,basereg,offset)  \
                        arm_store_membase_byte((inst), (reg), (basereg), 
(offset))

/*
 * Store a signed byte value to an offset from a pointer register.
 */
#define md_store_membase_sbyte(inst,reg,basereg,offset) \
                        arm_store_membase_sbyte((inst), (reg), (basereg), 
(offset))

/*
 * Store a short value to an offset from a pointer register.
 */
#define md_store_membase_short(inst,reg,basereg,offset) \
                        arm_store_membase_short((inst), (reg), (basereg), 
(offset))

/*
 * Store an unsigned short value to an offset from a pointer register.
 */
#define md_store_membase_ushort(inst,reg,basereg,offset)        \
                        arm_store_membase_ushort((inst), (reg), (basereg), 
(offset))

/*
 * Store a floating-point value to an offset from a pointer register.
 * If the system uses floating-point registers, then the value is
 * stored from "reg".  Otherwise it is stored from the top of the
 * floating-point stack.
 */
#define md_store_membase_float_32(inst,reg,basereg,offset)      \
                        do { ; } while (0)
#define md_store_membase_float_64(inst,reg,basereg,offset)      \
                        do { ; } while (0)
#define md_store_membase_float_native(inst,reg,basereg,offset)  \
                        do { ; } while (0)

/*
 * Add an immediate value to a register.
 */
#define md_add_reg_imm(inst,reg,imm)    \
                        arm_alu_reg_imm((inst), ARM_ADD, (reg), (reg), (imm))

/*
 * Subtract an immediate value from a register.
 */
#define md_sub_reg_imm(inst,reg,imm)    \
                        arm_alu_reg_imm((inst), ARM_SUB, (reg), (reg), (imm))

/*
 * Perform arithmetic and logical operations on 32-bit word registers.
 */
#define md_add_reg_reg_word_32(inst,reg1,reg2)  \
                        arm_alu_reg_reg((inst), ARM_ADD, (reg1), (reg1), (reg2))
#define md_sub_reg_reg_word_32(inst,reg1,reg2)  \
                        arm_alu_reg_reg((inst), ARM_SUB, (reg1), (reg1), (reg2))
#define md_mul_reg_reg_word_32(inst,reg1,reg2)  \
                        arm_mul_reg_reg((inst), (reg1), (reg1), (reg2))
#define md_div_reg_reg_word_32(inst,reg1,reg2)  \
                        do { ; } while (0)
#define md_udiv_reg_reg_word_32(inst,reg1,reg2) \
                        do { ; } while (0)
#define md_rem_reg_reg_word_32(inst,reg1,reg2)  \
                        do { ; } while (0)
#define md_urem_reg_reg_word_32(inst,reg1,reg2) \
                        do { ; } while (0)
#define md_neg_reg_word_32(inst,reg)    \
                        arm_alu_reg_imm((inst), ARM_RSB, (reg), (reg), 0)
#define md_and_reg_reg_word_32(inst,reg1,reg2)  \
                        arm_alu_reg_reg((inst), ARM_AND, (reg1), (reg1), (reg2))
#define md_xor_reg_reg_word_32(inst,reg1,reg2)  \
                        arm_alu_reg_reg((inst), ARM_XOR, (reg1), (reg1), (reg2))
#define md_or_reg_reg_word_32(inst,reg1,reg2)   \
                        arm_alu_reg_reg((inst), ARM_ORR, (reg1), (reg1), (reg2))
#define md_not_reg_word_32(inst,reg)    \
                        arm_alu_reg((inst), ARM_MVN, (reg), (reg))
#define md_shl_reg_reg_word_32(inst,reg1,reg2)  \
                        arm_shift_reg_reg((inst), ARM_SHL, (reg1), (reg1), 
(reg2))
#define md_shr_reg_reg_word_32(inst,reg1,reg2)  \
                        arm_shift_reg_reg((inst), ARM_SAR, (reg1), (reg1), 
(reg2))
#define md_ushr_reg_reg_word_32(inst,reg1,reg2) \
                        arm_shift_reg_reg((inst), ARM_SHR, (reg1), (reg1), 
(reg2))

/*
 * Convert word registers between various types.
 */
#define md_reg_to_byte(inst,reg)        \
                        arm_alu_reg_imm((inst), ARM_AND, (reg), (reg), 0xFF)
#define md_reg_to_sbyte(inst,reg)       \
                        do { \
                                arm_shift_reg_imm((inst), ARM_SHL, (reg), 
(reg), 24); \
                                arm_shift_reg_imm((inst), ARM_SAR, (reg), 
(reg), 24); \
                        } while (0)
#define md_reg_to_short(inst,reg)       \
                        do { \
                                arm_shift_reg_imm((inst), ARM_SHL, (reg), 
(reg), 16); \
                                arm_shift_reg_imm((inst), ARM_SAR, (reg), 
(reg), 16); \
                        } while (0)
#define md_reg_to_ushort(inst,reg)      \
                        do { \
                                arm_shift_reg_imm((inst), ARM_SHL, (reg), 
(reg), 16); \
                                arm_shift_reg_imm((inst), ARM_SHR, (reg), 
(reg), 16); \
                        } while (0)
#define md_reg_to_word_32(inst,reg)     \
                        do { ; } while (0)
#define md_reg_to_word_native(inst,reg) \
                        do { ; } while (0)

/*
 * Truncate floating point values to 32-bit or 64-bit.
 */
#define md_reg_to_float_32(inst,reg)    \
                        do { ; } while (0)
#define md_reg_to_float_64(inst,reg)    \
                        do { ; } while (0)

/*
 * Swap the top two items on the floating-point stack.
 */
#define md_freg_swap(inst)              do { ; } while (0)

/*
 * Jump back into the CVM interpreter to execute the instruction
 * at "pc".  If "label" is non-NULL, then it indicates the address
 * of the CVM instruction handler to jump directly to.
 */
#define md_jump_to_cvm(inst,pc,label)   \
                        do { \
                                /* TODO */ \
                        } while (0)

/*
 * Perform a clear operation at a memory base.
 */
#define md_clear_membase_start(inst)    \
                        do { \
                                arm_mov_reg_imm((inst), ARM_WORK, 0); \
                        } while (0)
#define md_clear_membase(inst,reg,offset)       \
                        do { \
                                arm_store_membase((inst), ARM_WORK, (reg), 
(offset)); \
                        } while (0)

/*
 * Load the effective address of a memory base into a register.
 */
#define md_lea_membase(inst,reg,basereg,offset) \
                        do { \
                                int __value = (int)(offset); \
                                arm_mov_reg_reg((inst), (reg), (basereg)); \
                                if(__value != 0) \
                                { \
                                        arm_alu_reg_imm((inst), ARM_ADD, (reg), 
(reg), __value); \
                                } \
                        } while (0)

/*
 * Move values between registers.
 */
#define md_mov_reg_reg(inst,dreg,sreg)  \
                        arm_mov_reg_reg((inst), (dreg), (sreg))

/*
 * Helper routine for the complex cases of "arm_mov_reg_imm".
 * TODO: make this static.
 */
arm_inst_ptr _arm_mov_reg_imm(arm_inst_ptr inst, int reg, int value)
{
        /* Handle bytes in various positions */
        if((value & 0x000000FF) == value)
        {
                arm_mov_reg_imm8(inst, reg, value);
                return inst;
        }
        else if((value & 0x0000FF00) == value)
        {
                arm_mov_reg_imm8_rotate(inst, reg, (value >> 8), 12);
                return inst;
        }
        else if((value & 0x00FF0000) == value)
        {
                arm_mov_reg_imm8_rotate(inst, reg, (value >> 16), 8);
                return inst;
        }
        else if((value & 0xFF000000) == value)
        {
                arm_mov_reg_imm8_rotate(inst, reg, ((value >> 24) & 0xFF), 4);
                return inst;
        }

        /* Handle inverted bytes in various positions */
        value = ~value;
        if((value & 0x000000FF) == value)
        {
                arm_mov_reg_imm8(inst, reg, value);
                arm_alu_reg(inst, ARM_MVN, reg, reg);
                return inst;
        }
        else if((value & 0x0000FF00) == value)
        {
                arm_mov_reg_imm8_rotate(inst, reg, (value >> 8), 12);
                arm_alu_reg(inst, ARM_MVN, reg, reg);
                return inst;
        }
        else if((value & 0x00FF0000) == value)
        {
                arm_mov_reg_imm8_rotate(inst, reg, (value >> 16), 8);
                arm_alu_reg(inst, ARM_MVN, reg, reg);
                return inst;
        }
        else if((value & 0xFF000000) == value)
        {
                arm_mov_reg_imm8_rotate(inst, reg, ((value >> 24) & 0xFF), 4);
                arm_alu_reg(inst, ARM_MVN, reg, reg);
                return inst;
        }

        /* Build the value the hard way, byte by byte */
        value = ~value;
        if((value & 0xFF000000) != 0)
        {
                arm_mov_reg_imm8_rotate(inst, reg, ((value >> 24) & 0xFF), 4);
                if((value & 0x00FF0000) != 0)
                {
                        arm_alu_reg_imm8_rotate
                                (inst, ARM_ADD, reg, reg, ((value >> 16) & 
0xFF), 8);
                }
                if((value & 0x0000FF00) != 0)
                {
                        arm_alu_reg_imm8_rotate
                                (inst, ARM_ADD, reg, reg, ((value >> 8) & 
0xFF), 12);
                }
                if((value & 0x000000FF) != 0)
                {
                        arm_alu_reg_imm8(inst, ARM_ADD, reg, reg, (value & 
0xFF));
                }
        }
        else if((value & 0x00FF0000) != 0)
        {
                arm_mov_reg_imm8_rotate(inst, reg, ((value >> 16) & 0xFF), 8);
                if((value & 0x0000FF00) != 0)
                {
                        arm_alu_reg_imm8_rotate
                                (inst, ARM_ADD, reg, reg, ((value >> 8) & 
0xFF), 12);
                }
                if((value & 0x000000FF) != 0)
                {
                        arm_alu_reg_imm8(inst, ARM_ADD, reg, reg, (value & 
0xFF));
                }
        }
        else if((value & 0x0000FF00) != 0)
        {
                arm_mov_reg_imm8_rotate(inst, reg, ((value >> 8) & 0xFF), 12);
                if((value & 0x000000FF) != 0)
                {
                        arm_alu_reg_imm8(inst, ARM_ADD, reg, reg, (value & 
0xFF));
                }
        }
        else
        {
                arm_mov_reg_imm8(inst, reg, (value & 0xFF));
        }
        return inst;
}

/*
 * Helper routine for the complex cases of "arm_alu_reg_imm".
 */
arm_inst_ptr _arm_alu_reg_imm(arm_inst_ptr inst, int opc,
                                                  int dreg, int sreg, int imm,
                                                  int saveWork)
{
        int tempreg;
        if(saveWork)
        {
                if(dreg != ARM_R2 && sreg != ARM_R2)
                {
                        tempreg = ARM_R2;
                }
                else if(dreg != ARM_R3 && sreg != ARM_R3)
                {
                        tempreg = ARM_R3;
                }
                else
                {
                        tempreg = ARM_R4;
                }
                arm_push_reg(inst, tempreg);
        }
        else
        {
                tempreg = ARM_WORK;
        }
        _arm_mov_reg_imm(inst, tempreg, imm);
        arm_alu_reg_reg(inst, opc, dreg, sreg, tempreg);
        if(saveWork)
        {
                arm_pop_reg(inst, tempreg);
        }
        return inst;
}

#ifdef  __cplusplus
};
#endif

#endif /* _ENGINE_MD_ARM_H */

--- NEW FILE ---
/*
 * md_default.h - Define missing macros to generic defaults.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _ENGINE_MD_DEFAULT_H
#define _ENGINE_MD_DEFAULT_H

#ifdef  __cplusplus
extern  "C" {
#endif

/*
 * Perform arithmetic and logical operations on native word registers.
 */
#if defined(IL_NATIVE_INT32) && !defined(md_add_reg_reg_word_native)
#define md_add_reg_reg_word_native(inst,reg1,reg2)      \
                        md_add_reg_reg_word_32((inst), (reg1), (reg2))
#define md_sub_reg_reg_word_native(inst,reg1,reg2)      \
                        md_sub_reg_reg_word_32((inst), (reg1), (reg2))
#define md_mul_reg_reg_word_native(inst,reg1,reg2)      \
                        md_mul_reg_reg_word_32((inst), (reg1), (reg2))
#define md_div_reg_reg_word_native(inst,reg1,reg2)      \
                        md_div_reg_reg_word_32((inst), (reg1), (reg2))
#define md_udiv_reg_reg_word_native(inst,reg1,reg2,regsused)    \
                        md_udiv_reg_reg_word_32((inst), (reg1), (reg2))
#define md_rem_reg_reg_word_native(inst,reg1,reg2,regsused)     \
                        md_rem_reg_reg_word_32((inst), (reg1), (reg2))
#define md_urem_reg_reg_word_native(inst,reg1,reg2,regsused)    \
                        md_urem_reg_reg_word_32((inst), (reg1), (reg2))
#define md_neg_reg_word_native(inst,reg)        \
                        md_neg_reg_word_32((inst), (reg))
#define md_and_reg_reg_word_native(inst,reg1,reg2)      \
                        md_and_reg_reg_word_32((inst), (reg1), (reg2))
#define md_xor_reg_reg_word_native(inst,reg1,reg2)      \
                        md_xor_reg_reg_word_32((inst), (reg1), (reg2))
#define md_or_reg_reg_word_native(inst,reg1,reg2)       \
                        md_or_reg_reg_word_32((inst), (reg1), (reg2))
#define md_not_reg_word_native(inst,reg)        \
                        md_not_reg_word_32((inst), (reg))
#define md_shl_reg_reg_word_native(inst,reg1,reg2)      \
                        md_shl_reg_reg_word_32((inst), (reg1), (reg2))
#define md_shr_reg_reg_word_native(inst,reg1,reg2,regsused)     \
                        md_shr_reg_reg_word_32((inst), (reg1), (reg2))
#define md_ushr_reg_reg_word_native(inst,reg1,reg2,regsused)    \
                        md_ushr_reg_reg_word_32((inst), (reg1), (reg2))
#endif

/*
 * Perform arithmetic operations on native float values.  If the system
 * uses a floating-point stack, then the register arguments are ignored.
 */
#if !defined(md_add_reg_reg_float)
#define md_add_reg_reg_float(inst,reg1,reg2)    \
                        do { ; } while (0)
#define md_sub_reg_reg_float(inst,reg1,reg2)    \
                        do { ; } while (0)
#define md_mul_reg_reg_float(inst,reg1,reg2)    \
                        do { ; } while (0)
#define md_div_reg_reg_float(inst,reg1,reg2)    \
                        do { ; } while (0)
#define md_rem_reg_reg_float(inst,reg1,reg2)    \
                        do { ; } while (0)
#define md_neg_reg_float(inst,reg)      \
                        do { ; } while (0)
#endif

#ifdef  __cplusplus
};
#endif

#endif /* _ENGINE_MD_DEFAULT_H */

--- NEW FILE ---
/*
 * md_x86.h - Machine-dependent definitions for x86.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _ENGINE_MD_X86_H
#define _ENGINE_MD_X86_H

#include "x86_codegen.h"

#ifdef  __cplusplus
extern  "C" {
#endif

/*
 * Register numbers in the standard register allocation order.
 * -1 is the list terminator.
 */
#define MD_REG_0                X86_EAX
#define MD_REG_1                X86_ECX
#define MD_REG_2                X86_EDX
#define MD_REG_3                X86_ESI
#define MD_REG_4                X86_EBP
#define MD_REG_5                -1
#define MD_REG_6                -1
#define MD_REG_7                -1
#define MD_REG_8                -1
#define MD_REG_9                -1
#define MD_REG_10               -1
#define MD_REG_11               -1
#define MD_REG_12               -1
#define MD_REG_13               -1
#define MD_REG_14               -1
#define MD_REG_15               -1

/*
 * Mask that indicates a floating-point register.
 */
#define MD_FREG_MASK    0x0010

/*
 * Floating point register numbers in the standard allocation order.
 * -1 is the list terminator.  The floating point register numbers
 * must include the MD_FREG_MASK value.
 */
#define MD_FREG_0               (MD_FREG_MASK | 0)
#define MD_FREG_1               (MD_FREG_MASK | 1)
#define MD_FREG_2               (MD_FREG_MASK | 2)
#define MD_FREG_3               (MD_FREG_MASK | 3)
#define MD_FREG_4               (MD_FREG_MASK | 4)
#define MD_FREG_5               (MD_FREG_MASK | 5)
#define MD_FREG_6               (MD_FREG_MASK | 6)
#define MD_FREG_7               (MD_FREG_MASK | 7)
#define MD_FREG_8               -1
#define MD_FREG_9               -1
#define MD_FREG_10              -1
#define MD_FREG_11              -1
#define MD_FREG_12              -1
#define MD_FREG_13              -1
#define MD_FREG_14              -1
#define MD_FREG_15              -1

/*
 * Set this to a non-zero value if floating-point registers are organised
 * in a stack (e.g. the x87 FPU).
 */
#define MD_FP_STACK_SIZE        8

/*
 * The register that contains the CVM program counter.  This may be
 * present in the standard register allocation order.  This can be
 * set to -1 if MD_STATE_ALREADY_IN_REGS is 0.
 */
#define MD_REG_PC               X86_ESI

/*
 * The register that contains the CVM stacktop pointer.  This must not
 * be present in the standard register allocation order.
 */
#define MD_REG_STACK    X86_EDI

/*
 * The register that contains the CVM frame pointer.  This must not
 * be present in the standard register allocation order.
 */
#define MD_REG_FRAME    X86_EBX

/*
 * Set this to 1 if "pc", "stacktop", and "frame" are already in
 * the above registers when unrolled code is entered.  i.e. the
 * CVM interpreter has manual assignments of registers to variables
 * in the file "cvm.c".  If the state is not already in registers,
 * then set this value to zero.
 */
#define MD_STATE_ALREADY_IN_REGS        1

/*
 * Registers that must be saved on the system stack prior to their use
 * in unrolled code for temporary stack values.
 */
#define MD_REGS_TO_BE_SAVED                     (1 << X86_EBP)

/*
 * Registers with special meanings (pc, stacktop, frame) that must
 * be saved if MD_STATE_ALREADY_IN_REGS is 0.
 */
#define MD_SPECIAL_REGS_TO_BE_SAVED     0

/*
 * Floating-point register numbers that must be saved.
 */
#define MD_FREGS_TO_BE_SAVED            0

/*
 * Set this to 1 if the CPU has integer division operations.
 * Set it to zero if integer division is too hard to be performed
 * inline using a simple opcode.
 */
#define MD_HAS_INT_DIVISION                     0

/*
 * Type of the instruction pointer for outputting code.
 */
typedef unsigned char *md_inst_ptr;

/*
 * Push a word register onto the system stack.
 */
#define md_push_reg(inst,reg)   x86_push_reg((inst), (reg))

/*
 * Pop a word register from the system stack.
 */
#define md_pop_reg(inst,reg)    x86_pop_reg((inst), (reg))

/*
 * Discard the contents of a floating-point register.
 */
#define md_discard_freg(inst,reg)       do { ; } while (0)

/*
 * Load a 32-bit integer constant into a register.  This will sign-extend
 * if the native word size is larger.
 */
#define md_load_const_32(inst,reg,value)        \
                        x86_mov_reg_imm((inst), (reg), (value))

/*
 * Load a native integer constant into a register.
 */
#define md_load_const_native(inst,reg,value)    \
                        x86_mov_reg_imm((inst), (reg), (value))

/*
 * Load a 32-bit word register from an offset from a pointer register.
 * This will sign-extend if the native word size is larger.
 */
#define md_load_membase_word_32(inst,reg,basereg,offset)        \
                        x86_mov_reg_membase((inst), (reg), (basereg), (offset), 
4)

/*
 * Load a native-sized word register from an offset from a pointer register.
 */
#define md_load_membase_word_native(inst,reg,basereg,offset)    \
                        x86_mov_reg_membase((inst), (reg), (basereg), (offset), 
4)

/*
 * Load a byte value from an offset from a pointer register.
 */
#define md_load_membase_byte(inst,reg,basereg,offset)   \
                        x86_widen_membase((inst), (reg), (basereg), (offset), 
0, 0)

/*
 * Load a signed byte value from an offset from a pointer register.
 */
#define md_load_membase_sbyte(inst,reg,basereg,offset)  \
                        x86_widen_membase((inst), (reg), (basereg), (offset), 
1, 0)

/*
 * Load a short value from an offset from a pointer register.
 */
#define md_load_membase_short(inst,reg,basereg,offset)  \
                        x86_widen_membase((inst), (reg), (basereg), (offset), 
1, 1)

/*
 * Load an unsigned short value from an offset from a pointer register.
 */
#define md_load_membase_ushort(inst,reg,basereg,offset) \
                        x86_widen_membase((inst), (reg), (basereg), (offset), 
0, 1)

/*
 * Load a floating-point value from an offset from a pointer register.
 * If the system uses floating-point registers, then the value is
 * loaded into "reg".  Otherwise it is loaded onto the top of the
 * floating-point stack.
 */
#define md_load_membase_float_32(inst,reg,basereg,offset)       \
                        x86_fld_membase((inst), (basereg), (offset), 0)
#define md_load_membase_float_64(inst,reg,basereg,offset)       \
                        x86_fld_membase((inst), (basereg), (offset), 1)
#define md_load_membase_float_native(inst,reg,basereg,offset)   \
                        x86_fld80_membase((inst), (basereg), (offset))

/*
 * Store a 32-bit word register to an offset from a pointer register.
 */
#define md_store_membase_word_32(inst,reg,basereg,offset)       \
                        x86_mov_membase_reg((inst), (basereg), (offset), (reg), 
4)

/*
 * Store a native-sized word register to an offset from a pointer register.
 */
#define md_store_membase_word_native(inst,reg,basereg,offset)   \
                        x86_mov_membase_reg((inst), (basereg), (offset), (reg), 
4)

/*
 * Store a byte value to an offset from a pointer register.
 */
static md_inst_ptr _x86_mov_membase_reg_byte
                        (md_inst_ptr inst, int basereg, int offset, int srcreg)
{
        if(srcreg == X86_EAX || srcreg == X86_EBX ||
           srcreg == X86_ECX || srcreg == X86_EDX)
        {
                x86_mov_membase_reg(inst, basereg, offset, srcreg, 1);
        }
        else if(basereg != X86_EAX)
        {
                x86_push_reg(inst, X86_EAX);
                x86_mov_reg_reg(inst, X86_EAX, srcreg, 4);
                x86_mov_membase_reg(inst, basereg, offset, X86_EAX, 1);
                x86_pop_reg(inst, X86_EAX);
        }
        else
        {
                x86_push_reg(inst, X86_EDX);
                x86_mov_reg_reg(inst, X86_EDX, srcreg, 4);
                x86_mov_membase_reg(inst, basereg, offset, X86_EDX, 1);
                x86_pop_reg(inst, X86_EDX);
        }
        return inst;
}
#define md_store_membase_byte(inst,reg,basereg,offset)  \
                        do { \
                                (inst) = _x86_mov_membase_reg_byte      \
                                        ((inst), (basereg), (int)(offset), 
(reg)); \
                        } while (0)

/*
 * Store a signed byte value to an offset from a pointer register.
 */
#define md_store_membase_sbyte(inst,reg,basereg,offset) \
                        md_store_membase_byte((inst), (reg), (basereg), 
(offset))

/*
 * Store a short value to an offset from a pointer register.
 */
#define md_store_membase_short(inst,reg,basereg,offset) \
                        x86_mov_membase_reg((inst), (basereg), (offset), (reg), 
2)

/*
 * Store an unsigned short value to an offset from a pointer register.
 */
#define md_store_membase_ushort(inst,reg,basereg,offset)        \
                        x86_mov_membase_reg((inst), (basereg), (offset), (reg), 
2)

/*
 * Store a floating-point value to an offset from a pointer register.
 * If the system uses floating-point registers, then the value is
 * stored from "reg".  Otherwise it is stored from the top of the
 * floating-point stack.
 */
#define md_store_membase_float_32(inst,reg,basereg,offset)      \
                        x86_fst_membase((inst), (basereg), (offset), 0, 1)
#define md_store_membase_float_64(inst,reg,basereg,offset)      \
                        x86_fst_membase((inst), (basereg), (offset), 1, 1)
#define md_store_membase_float_native(inst,reg,basereg,offset)  \
                        x86_fst80_membase((inst), (basereg), (offset))

/*
 * Add an immediate value to a register.
 */
#define md_add_reg_imm(inst,reg,imm)    \
                        x86_alu_reg_imm((inst), X86_ADD, (reg), (imm))

/*
 * Subtract an immediate value from a register.
 */
#define md_sub_reg_imm(inst,reg,imm)    \
                        x86_alu_reg_imm((inst), X86_SUB, (reg), (imm))

/*
 * Perform arithmetic and logical operations on 32-bit word registers.
 *
 * Note: x86 divisions and shifts are handled elsewhere, because they are hard.
 */
#define md_add_reg_reg_word_32(inst,reg1,reg2)  \
                        x86_alu_reg_reg((inst), X86_ADD, (reg1), (reg2))
#define md_sub_reg_reg_word_32(inst,reg1,reg2)  \
                        x86_alu_reg_reg((inst), X86_SUB, (reg1), (reg2))
#define md_mul_reg_reg_word_32(inst,reg1,reg2)  \
                        x86_imul_reg_reg((inst), (reg1), (reg2))
#define md_div_reg_reg_word_32(inst,reg1,reg2)  \
                        do { ; } while (0)
#define md_udiv_reg_reg_word_32(inst,reg1,reg2) \
                        do { ; } while (0)
#define md_rem_reg_reg_word_32(inst,reg1,reg2)  \
                        do { ; } while (0)
#define md_urem_reg_reg_word_32(inst,reg1,reg2) \
                        do { ; } while (0)
#define md_neg_reg_word_32(inst,reg)    \
                        x86_neg_reg((inst), (reg))
#define md_and_reg_reg_word_32(inst,reg1,reg2)  \
                        x86_alu_reg_reg((inst), X86_AND, (reg1), (reg2))
#define md_xor_reg_reg_word_32(inst,reg1,reg2)  \
                        x86_alu_reg_reg((inst), X86_XOR, (reg1), (reg2))
#define md_or_reg_reg_word_32(inst,reg1,reg2)   \
                        x86_alu_reg_reg((inst), X86_OR, (reg1), (reg2))
#define md_not_reg_word_32(inst,reg)    \
                        x86_not_reg((inst), (reg))
#define md_shl_reg_reg_word_32(inst,reg1,reg2)  \
                        do { ; } while (0)
#define md_shr_reg_reg_word_32(inst,reg1,reg2)  \
                        do { ; } while (0)
#define md_ushr_reg_reg_word_32(inst,reg1,reg2) \
                        do { ; } while (0)

/*
 * Perform arithmetic operations on native float values.  If the system
 * uses a floating-point stack, then the register arguments are ignored.
 *
 * Note: x86 remainder is handled elsewhere because it is complicated.
 */
#define md_add_reg_reg_float(inst,reg1,reg2)    \
                        x86_fp_op_reg((inst), X86_FADD, 1, 1)
#define md_sub_reg_reg_float(inst,reg1,reg2)    \
                        x86_fp_op_reg((inst), X86_FSUB, 1, 1)
#define md_mul_reg_reg_float(inst,reg1,reg2)    \
                        x86_fp_op_reg((inst), X86_FMUL, 1, 1)
#define md_div_reg_reg_float(inst,reg1,reg2)    \
                        x86_fp_op_reg((inst), X86_FDIV, 1, 1)
#define md_rem_reg_reg_float(inst,reg1,reg2)    \
                        do { ; } while (0)
#define md_neg_reg_float(inst,reg)      \
                        x86_fchs((inst))

/*
 * Convert word registers between various types.
 */
#define md_reg_to_byte(inst,reg)        \
                        x86_widen_reg((inst), (reg), (reg), 0, 0)
#define md_reg_to_sbyte(inst,reg)       \
                        x86_widen_reg((inst), (reg), (reg), 1, 0)
#define md_reg_to_short(inst,reg)       \
                        x86_widen_reg((inst), (reg), (reg), 1, 1)
#define md_reg_to_ushort(inst,reg)      \
                        x86_widen_reg((inst), (reg), (reg), 0, 1)
#define md_reg_to_word_32(inst,reg)     \
                        do { ; } while (0)
#define md_reg_to_word_native(inst,reg) \
                        do { ; } while (0)

/*
 * Truncate floating point values to 32-bit or 64-bit.
 */
#define md_reg_to_float_32(inst,reg)    \
                        do { \
                                x86_alu_reg_imm((inst), X86_SUB, X86_ESP, 4); \
                                x86_fst_membase((inst), X86_ESP, 0, 0, 1); \
                                x86_fld_membase((inst), X86_ESP, 0, 0); \
                                x86_alu_reg_imm((inst), X86_ADD, X86_ESP, 4); \
                        } while (0)
#define md_reg_to_float_64(inst,reg)    \
                        do { \
                                x86_alu_reg_imm((inst), X86_SUB, X86_ESP, 8); \
                                x86_fst_membase((inst), X86_ESP, 0, 1, 1); \
                                x86_fld_membase((inst), X86_ESP, 0, 1); \
                                x86_alu_reg_imm((inst), X86_ADD, X86_ESP, 8); \
                        } while (0)

/*
 * Swap the top two items on the floating-point stack.
 */
#define md_freg_swap(inst)              x86_fxch((inst), 1)

/*
 * Jump back into the CVM interpreter to execute the instruction
 * at "pc".  If "label" is non-NULL, then it indicates the address
 * of the CVM instruction handler to jump directly to.
 */
#define md_jump_to_cvm(inst,pc,label)   \
                        do { \
                                x86_mov_reg_imm((inst), MD_REG_PC, (int)pc); \
                                if((label)) \
                                { \
                                        x86_jump_code((inst), label); \
                                } \
                                else \
                                { \
                                        x86_jump_membase((inst), MD_REG_PC, 0); 
\
                                } \
                        } while (0)

/*
 * Perform a clear operation at a memory base.
 */
#define md_clear_membase_start(inst)    do { ; } while (0)
#define md_clear_membase(inst,reg,offset)       \
                        do { \
                                x86_mov_membase_imm((inst), (reg), (offset), 0, 
4); \
                        } while (0)

/*
 * Load the effective address of a memory base into a register.
 */
#define md_lea_membase(inst,reg,basereg,offset) \
                        do { \
                                int __value = (int)(offset); \
                                if(!__value) \
                                { \
                                        x86_mov_reg_reg((inst), (reg), 
(basereg), 4); \
                                } \
                                else \
                                { \
                                        x86_lea_membase((inst), (reg), 
(basereg), __value); \
                                } \
                        } while (0)

/*
 * Move values between registers.
 */
#define md_mov_reg_reg(inst,dreg,sreg)  \
                        x86_mov_reg_reg((inst), (dreg), (sreg), 4)

#ifdef  __cplusplus
};
#endif

#endif /* _ENGINE_MD_X86_H */

--- NEW FILE ---
/*
 * unroll.c - CVM unrolling module.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
[...1422 lines suppressed...]
int _ILCVMUnrollInit(void)
{
        return 1;
}

int _ILCVMUnrollPossible(void)
{
        return 0;
}

int _ILCVMUnrollMethod(ILCoder *coder, unsigned char *pc, ILMethod *method)
{
        return 0;
}

#endif /* !IL_CVM_DIRECT_UNROLLED */

#ifdef  __cplusplus
};
#endif

--- NEW FILE ---
/*
 * unroll_var.c - Variable handling for CVM unrolling.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifdef IL_UNROLL_CASES

case COP_ILOAD_0:
{
        /* Unroll an access to frame variable 0 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 0, MD_REG1_32BIT);
        if(reg != -1)
        {
                md_load_membase_word_32(unroll.out, reg, MD_REG_FRAME, 0);
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PLOAD_0:
{
        /* Unroll an access to frame variable 0 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 0, MD_REG1_NATIVE);
        if(reg != -1)
        {
                md_load_membase_word_native(unroll.out, reg, MD_REG_FRAME, 0);
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ILOAD_1:
{
        /* Unroll an access to frame variable 1 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 1, MD_REG1_32BIT);
        if(reg != -1)
        {
                md_load_membase_word_32(unroll.out, reg,
                                                                MD_REG_FRAME, 
sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PLOAD_1:
{
        /* Unroll an access to frame variable 1 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 1, MD_REG1_NATIVE);
        if(reg != -1)
        {
                md_load_membase_word_native(unroll.out, reg,
                                                                        
MD_REG_FRAME, sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ILOAD_2:
{
        /* Unroll an access to frame variable 2 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 2, MD_REG1_32BIT);
        if(reg != -1)
        {
                md_load_membase_word_32(unroll.out, reg,
                                                                MD_REG_FRAME, 2 
* sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PLOAD_2:
{
        /* Unroll an access to frame variable 2 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 2, MD_REG1_NATIVE);
        if(reg != -1)
        {
                md_load_membase_word_native(unroll.out, reg,
                                                                        
MD_REG_FRAME, 2 * sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ILOAD_3:
{
        /* Unroll an access to frame variable 3 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 3, MD_REG1_32BIT);
        if(reg != -1)
        {
                md_load_membase_word_32(unroll.out, reg,
                                                                MD_REG_FRAME, 3 
* sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PLOAD_3:
{
        /* Unroll an access to frame variable 3 */
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, 3, MD_REG1_NATIVE);
        if(reg != -1)
        {
                md_load_membase_word_native(unroll.out, reg,
                                                                        
MD_REG_FRAME, 3 * sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ILOAD:
{
        /* Unroll an access to an arbitrary frame variable */
        unsigned temp = CVM_ARG_WIDE_SMALL;
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, temp, MD_REG1_32BIT);
        if(reg != -1)
        {
                md_load_membase_word_32(unroll.out, reg,
                                                                MD_REG_FRAME, 
temp * sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_WIDE_SMALL);
}
break;

case COP_PLOAD:
{
        /* Unroll an access to an arbitrary frame variable */
        unsigned temp = CVM_ARG_WIDE_SMALL;
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, temp, MD_REG1_NATIVE);
        if(reg != -1)
        {
                md_load_membase_word_native(unroll.out, reg,
                                                                    
MD_REG_FRAME, temp * sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_WIDE_SMALL);
}
break;

case COP_BLOAD:
{
        /* Unroll an access to a byte frame variable */
        unsigned temp = CVM_ARG_BYTE;
        UNROLL_START();
        reg = GetCachedWordRegister(&unroll, temp, MD_REG1_NATIVE);
        if(reg != -1)
        {
                md_load_membase_byte(unroll.out, reg,
                                                         MD_REG_FRAME, temp * 
sizeof(CVMWord));
        }
        MODIFY_UNROLL_PC(CVM_LEN_BYTE);
}
break;

case COP_ISTORE_0:
{
        /* Unroll a store to frame variable 0 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_32BIT);
        md_store_membase_word_32(unroll.out, reg, MD_REG_FRAME, 0);
        FreeTopRegister(&unroll, 0);
        if(unroll.thisValidated > 0)
        {
                /* The "this" variable must be re-validated */
                unroll.thisValidated = 0;
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PSTORE_0:
{
        /* Unroll a store to frame variable 0 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_NATIVE);
        md_store_membase_word_native(unroll.out, reg, MD_REG_FRAME, 0);
        FreeTopRegister(&unroll, 0);
        if(unroll.thisValidated > 0)
        {
                /* The "this" variable must be re-validated */
                unroll.thisValidated = 0;
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ISTORE_1:
{
        /* Unroll a store to frame variable 1 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_32BIT);
        md_store_membase_word_32(unroll.out, reg,
                                                         MD_REG_FRAME, 
sizeof(CVMWord));
        FreeTopRegister(&unroll, 1);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PSTORE_1:
{
        /* Unroll a store to frame variable 1 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_NATIVE);
        md_store_membase_word_native(unroll.out, reg,
                                                                 MD_REG_FRAME, 
sizeof(CVMWord));
        FreeTopRegister(&unroll, 1);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ISTORE_2:
{
        /* Unroll a store to frame variable 2 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_32BIT);
        md_store_membase_word_32(unroll.out, reg,
                                                         MD_REG_FRAME, 2 * 
sizeof(CVMWord));
        FreeTopRegister(&unroll, 2);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PSTORE_2:
{
        /* Unroll a store to frame variable 2 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_NATIVE);
        md_store_membase_word_native(unroll.out, reg,
                                                                 MD_REG_FRAME, 
2 * sizeof(CVMWord));
        FreeTopRegister(&unroll, 2);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ISTORE_3:
{
        /* Unroll a store to frame variable 3 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_32BIT);
        md_store_membase_word_32(unroll.out, reg,
                                                         MD_REG_FRAME, 3 * 
sizeof(CVMWord));
        FreeTopRegister(&unroll, 3);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_PSTORE_3:
{
        /* Unroll a store to frame variable 3 */
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_NATIVE);
        md_store_membase_word_native(unroll.out, reg,
                                                                 MD_REG_FRAME, 
3 * sizeof(CVMWord));
        FreeTopRegister(&unroll, 3);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_ISTORE:
{
        /* Unroll a store to an arbitrary frame variable */
        unsigned temp = CVM_ARG_WIDE_SMALL;
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_32BIT);
        md_store_membase_word_32(unroll.out, reg,
                                                     MD_REG_FRAME, temp * 
sizeof(CVMWord));
        FreeTopRegister(&unroll, temp);
        if(temp == 0 && unroll.thisValidated > 0)
        {
                /* The "this" variable must be re-validated */
                unroll.thisValidated = 0;
        }
        MODIFY_UNROLL_PC(CVM_LEN_WIDE_SMALL);
}
break;

case COP_PSTORE:
{
        /* Unroll a store to an arbitrary frame variable */
        unsigned temp = CVM_ARG_WIDE_SMALL;
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_NATIVE);
        md_store_membase_word_native(unroll.out, reg,
                                                         MD_REG_FRAME, temp * 
sizeof(CVMWord));
        FreeTopRegister(&unroll, temp);
        if(temp == 0 && unroll.thisValidated > 0)
        {
                /* The "this" variable must be re-validated */
                unroll.thisValidated = 0;
        }
        MODIFY_UNROLL_PC(CVM_LEN_WIDE_SMALL);
}
break;

case COP_BSTORE:
{
        /* Unroll a store to a byte frame variable */
        unsigned temp = CVM_ARG_BYTE;
        UNROLL_START();
        reg = GetTopWordRegister(&unroll, MD_REG1_32BIT);
        md_store_membase_byte(unroll.out, reg, MD_REG_FRAME,
                                                  temp * sizeof(CVMWord));
        FreeTopRegister(&unroll, temp);
        MODIFY_UNROLL_PC(CVM_LEN_BYTE);
}
break;

case COP_WADDR:
{
        /* Get the address of a frame word */
        unsigned temp = CVM_ARG_WIDE_SMALL;
        UNROLL_START();
        reg = GetWordRegister(&unroll, MD_REG1_NATIVE);
        md_lea_membase(unroll.out, reg, MD_REG_FRAME, temp * sizeof(CVMWord));
        if(!temp)
        {
                /* We don't know if someone might write to this address,
                   so we have to assume that "this" will need to be
                   validated always from now on */
                unroll.thisValidated = -1;
        }
        MODIFY_UNROLL_PC(CVM_LEN_WIDE_SMALL);
}
break;

case COP_MK_LOCAL_1:
{
        /* Make a single local variable word */
        UNROLL_START();
        FlushRegisterStack(&unroll);
        md_clear_membase_start(unroll.out);
        md_clear_membase(unroll.out, MD_REG_STACK, unroll.stackHeight);
        unroll.stackHeight += sizeof(CVMWord);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_MK_LOCAL_2:
{
        /* Make two local variable words */
        UNROLL_START();
        FlushRegisterStack(&unroll);
        md_clear_membase_start(unroll.out);
        md_clear_membase(unroll.out, MD_REG_STACK, unroll.stackHeight);
        md_clear_membase(unroll.out, MD_REG_STACK,
                                         unroll.stackHeight + sizeof(CVMWord));
        unroll.stackHeight += 2 * sizeof(CVMWord);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_MK_LOCAL_3:
{
        /* Make three local variable words */
        UNROLL_START();
        FlushRegisterStack(&unroll);
        md_clear_membase_start(unroll.out);
        md_clear_membase(unroll.out, MD_REG_STACK, unroll.stackHeight);
        md_clear_membase(unroll.out, MD_REG_STACK,
                                         unroll.stackHeight + sizeof(CVMWord));
        md_clear_membase(unroll.out, MD_REG_STACK,
                                         unroll.stackHeight + 2 * 
sizeof(CVMWord));
        unroll.stackHeight += 3 * sizeof(CVMWord);
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_DUP:
{
        /* Duplicate the top word on the stack */
        UNROLL_START();
        reg = PeekTopWordRegister(&unroll);
        if(reg != -1)
        {
                /* The top is already in a register, so move it to a new 
register */
                reg2 = GetWordRegister(&unroll, GetTopRegisterFlags(&unroll));
                if(unroll.pseudoStackSize > 1)
                {
                        md_mov_reg_reg(unroll.out, reg2, reg);
                }
                else
                {
                        /* "GetWordRegister" flushed all registers, so the value
                           we want to duplicate is now on the CVM stack */
                        if(GetTopRegisterFlags(&unroll))
                        {
                                md_load_membase_word_native
                                                (unroll.out, reg2, MD_REG_STACK,
                                             unroll.stackHeight - 
sizeof(CVMWord));
                        }
                        else
                        {
                                md_load_membase_word_32
                                                (unroll.out, reg2, MD_REG_STACK,
                                                 unroll.stackHeight - 
sizeof(CVMWord));
                        }
                }
        }
        else
        {
        #ifdef IL_NATIVE_INT32
                /* The top is on the CVM stack */
                reg = GetWordRegister(&unroll, MD_REG1_32BIT);
                md_load_membase_word_32
                                (unroll.out, reg,
                                 MD_REG_STACK, unroll.stackHeight - 
sizeof(CVMWord));
        #else
                /* We don't know if the top is 32-bit or native, so copy
                   the entire native word but leave it on the CVM stack.
                   A later reload will determine the true size */
                FlushRegisterStack(&unroll);
                md_load_membase_word_native
                                (unroll.out, MD_REG_0,
                                 MD_REG_STACK, unroll.stackHeight - 
sizeof(CVMWord));
                md_store_membase_word_native
                                (unroll.out, MD_REG_0, MD_REG_STACK, 
unroll.stackHeight);
                unroll.stackHeight += sizeof(CVMWord);
        #endif
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

case COP_POP:
{
        /* Pop the top word on the stack */
        UNROLL_START();
        reg = PeekTopWordRegister(&unroll);
        if(reg != -1)
        {
                /* Abandon the register's contents */
                FreeTopRegister(&unroll, -1);
        }
        else
        {
                /* Flush the register stack and then decrease its height */
                FlushRegisterStack(&unroll);
                unroll.stackHeight -= sizeof(CVMWord);
        }
        MODIFY_UNROLL_PC(CVM_LEN_NONE);
}
break;

#endif /* IL_UNROLL_CASES */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]