[Top][All Lists]
[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 */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [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,
Rhys Weatherley <address@hidden> <=