[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnet/engine md_ppc.h, NONE, 1.1 ppc_codegen.h
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnet/engine md_ppc.h, NONE, 1.1 ppc_codegen.h, NONE, 1.1 |
Date: |
Mon, 04 Aug 2003 22:25:48 -0400 |
Update of /cvsroot/dotgnu-pnet/pnet/engine
In directory subversions:/tmp/cvs-serv32471/engine
Added Files:
md_ppc.h ppc_codegen.h
Log Message:
Check in the early stages of the PPC unroller macros.
--- NEW FILE ---
/*
* md_ppc.h - Machine-dependent definitions for PowerPC.
*
* 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_PPC_H
#define _ENGINE_MD_PPC_H
#include "ppc_codegen.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Register numbers in the standard register allocation order.
* -1 is the list terminator.
*
* The register allocation order is the same as that used by gcc
* for general purpose registers that aren't saved.
*
* Note: "r12" is designated as a work register by "ppc_codegen.h"
* so we cannot use it for general allocation here.
*/
#define MD_REG_0 PPC_R9
#define MD_REG_1 PPC_R11
#define MD_REG_2 PPC_R10
#define MD_REG_3 PPC_R8
#define MD_REG_4 PPC_R7
#define MD_REG_5 PPC_R6
#define MD_REG_6 PPC_R5
#define MD_REG_7 PPC_R4
#define MD_REG_8 PPC_R3
#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 PPC_R18
/*
* The register that contains the CVM stacktop pointer. This must not
* be present in the standard register allocation order.
*/
#define MD_REG_STACK PPC_R19
/*
* The register that contains the CVM frame pointer. This must not
* be present in the standard register allocation order.
*/
#define MD_REG_FRAME PPC_R20
/*
* 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 0
/*
* 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 /* TODO */
/*
* Set to 1 if 64-bit register pairs are stored in little-endian order.
*/
#define MD_LITTLE_ENDIAN_LONGS 0
/*
* Type of the instruction pointer for outputting code.
*/
typedef ppc_inst_ptr md_inst_ptr;
/*
* Push a word register onto the system stack.
*/
#define md_push_reg(inst,reg) ppc_push_reg((inst), (reg))
/*
* Pop a word register from the system stack.
*/
#define md_pop_reg(inst,reg) ppc_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) \
ppc_mov_reg_imm((inst), (reg), (value))
/*
* Load a native integer constant into a register.
*/
#define md_load_const_native(inst,reg,value) \
ppc_mov_reg_imm((inst), (reg), (value))
/*
* Load a 32-bit floating-point constant into a register. The constant
* is at a particular memory location. If the system does not use
* floating-point registers, then load onto the top of the stack.
*/
#define md_load_const_float_32(inst,reg,mem) do { ; } while (0)
/*
* Load a 64-bit floating-point constant into a register. The constant
* is at a particular memory location. If the system does not use
* floating-point registers, then load onto the top of the stack.
*/
#define md_load_const_float_64(inst,reg,mem) do { ; } while (0)
/*
* Load the 32-bit constant zero into a register. This will zero-extend
* if the native word size is larger.
*/
#define md_load_zero_32(inst,reg) \
ppc_mov_reg_imm((inst), (reg), 0)
/*
* Load the native constant zero into a register.
*/
#define md_load_zero_native(inst,reg) \
ppc_mov_reg_imm((inst), (reg), 0)
/*
* 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) \
ppc_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) \
ppc_load_membase((inst), (reg), (basereg), (offset))
/*
* Load a 64-bit word value from an offset from a pointer register
* as a pair of 32-bit registers. Only used on 32-bit platforms.
*/
#define md_load_membase_word_64(inst,lreg,hreg,basereg,offset) \
do { \
ppc_load_membase((inst), (lreg), (basereg),
(offset) + 4); \
ppc_load_membase((inst), (hreg), (basereg),
(offset)); \
} while (0)
/*
* Load a byte value from an offset from a pointer register.
*/
#define md_load_membase_byte(inst,reg,basereg,offset) \
ppc_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) \
ppc_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) \
ppc_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) \
ppc_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) \
ppc_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) \
ppc_store_membase((inst), (reg), (basereg), (offset))
/*
* Store a pair of 32-bit word registers to an offset from a pointer
* register as a 64-bit value. Only used on 32-bit platforms.
*/
#define md_store_membase_word_64(inst,lreg,hreg,basereg,offset) \
do { \
ppc_store_membase((inst), (lreg), (basereg),
(offset) + 4); \
ppc_store_membase((inst), (hreg), (basereg),
(offset)); \
} while (0)
/*
* Store a byte value to an offset from a pointer register.
*/
#define md_store_membase_byte(inst,reg,basereg,offset) \
ppc_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) \
ppc_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) \
ppc_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) \
ppc_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) \
ppc_add_reg_imm((inst), (reg), (reg), (imm))
/*
* Subtract an immediate value from a register.
*/
#define md_sub_reg_imm(inst,reg,imm) \
ppc_sub_reg_imm((inst), (reg), (reg), (imm))
/*
* Perform arithmetic and logical operations on 32-bit word registers.
*/
#define md_add_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_dss((inst), PPC_ADD, (reg1), (reg1), (reg2))
#define md_sub_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_dss((inst), PPC_SUBF, (reg1), (reg2),
(reg1))
#define md_mul_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_dss((inst), PPC_MUL, (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) \
ppc_alu_reg_ds((inst), PPC_NEG, (reg), (reg))
#define md_and_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_sds((inst), PPC_AND, (reg1), (reg1), (reg2))
#define md_xor_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_sds((inst), PPC_XOR, (reg1), (reg1), (reg2))
#define md_or_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_sds((inst), PPC_OR, (reg1), (reg1), (reg2))
#define md_not_reg_word_32(inst,reg) \
ppc_alu_reg_sds((inst), PPC_NOR, (reg), (reg), (reg))
#define md_shl_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_sds((inst), PPC_SL, (reg1), (reg1), (reg2))
#define md_shr_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_sds((inst), PPC_SRA, (reg1), (reg1), (reg2))
#define md_ushr_reg_reg_word_32(inst,reg1,reg2) \
ppc_alu_reg_sds((inst), PPC_SR, (reg1), (reg1), (reg2))
/*
* Perform arithmetic on 64-bit values represented as 32-bit word pairs.
*/
#define md_add_reg_reg_word_64(inst,lreg1,hreg1,lreg2,hreg2) \
do { \
ppc_alu_cc_reg_dss((inst), PPC_ADDC, \
(lreg1),
(lreg1), (lreg2)); \
ppc_alu_reg_dss((inst), PPC_ADDE, (hreg1),
(hreg1), (hreg2)); \
} while (0)
#define md_sub_reg_reg_word_64(inst,lreg1,hreg1,lreg2,hreg2) \
do { \
ppc_alu_cc_reg_dss((inst), PPC_SUBFC, \
(lreg1),
(lreg2), (lreg1)); \
ppc_alu_reg_dss((inst), PPC_SUBFE, \
(hreg1),
(hreg2), (hreg1)); \
} while (0)
#define md_neg_reg_word_64(inst,lreg,hreg) \
do { \
ppc_alu_reg_sds((inst), PPC_NOR, (lreg),
(lreg), (lreg)); \
ppc_alu_reg_sds((inst), PPC_NOR, (hreg),
(hreg), (hreg)); \
ppc_mov_reg_imm((inst), PPC_WORK, 1); \
ppc_mov_reg_imm((inst), PPC_R0, 0); \
ppc_alu_cc_reg_dss((inst), PPC_ADDC, \
(lreg),
(lreg), PPC_WORK); \
ppc_alu_reg_dss((inst), PPC_ADDE, (hreg),
(hreg), PPC_R0); \
} while (0)
/*
* Convert word registers between various types.
*/
#define md_reg_to_byte(inst,reg) \
do { \
ppc_and_reg_imm((inst), (reg), (reg), 0xFF); \
} while (0)
#define md_reg_to_sbyte(inst,reg) \
do { \
ppc_alu_reg_sd((inst), PPC_EXTSB, (reg),
(reg)); \
} while (0)
#define md_reg_to_short(inst,reg) \
do { \
ppc_alu_reg_sd((inst), PPC_EXTSH, (reg),
(reg)); \
} while (0)
#define md_reg_to_ushort(inst,reg) \
do { \
ppc_and_reg_imm((inst), (reg), (reg), 0xFFFF); \
} while (0)
#define md_reg_to_word_32(inst,reg) \
do { ; } while (0)
#define md_reg_to_word_native(inst,reg) \
do { ; } while (0)
#define md_reg_to_word_native_un(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 { \
int offset; \
if(!(label)) \
{ \
/* Jump to the contents of the
specified PC */ \
arm_load_membase((inst), MD_REG_PC,
ARM_PC, 0); \
arm_load_membase((inst), ARM_PC,
MD_REG_PC, 0); \
*((inst)++) = (unsigned int)(pc); \
} \
else \
{ \
/* Load "pc" back into the CVM
interpreter's frame */ \
/* and then jump directly to
instruction handler at */ \
/* "label". This avoids the need for
an indirect */ \
/* jump instruction */ \
arm_load_membase(unroll->out,
MD_REG_PC, ARM_PC, 0); \
offset = (int)(((unsigned char
*)(label)) - \
(((unsigned char
*)(inst)) + 8)); \
if(offset >= -0x04000000 && offset <
0x04000000) \
{ \
arm_jump_imm((inst), offset); \
*((inst)++) = (unsigned
int)(pc); \
} \
else \
{ \
arm_load_membase(unroll->out,
ARM_PC, ARM_PC, 0); \
*((inst)++) = (unsigned
int)(pc); \
*((inst)++) = (unsigned
int)(label); \
} \
} \
} while (0)
/*
* Jump to a program counter that is defined by a switch table.
*/
#define md_switch(inst,reg,table) \
do { \
arm_load_membase((inst), ARM_WORK, ARM_PC, 4); \
arm_load_memindex((inst), MD_REG_PC, ARM_WORK,
(reg)); \
arm_load_membase((inst), ARM_PC, MD_REG_PC, 0);
\
*((inst)++) = (unsigned int)(table); \
} while (0)
/*
* Perform a clear operation at a memory base.
*/
#define md_clear_membase_start(inst) \
do { \
ppc_mov_reg_imm((inst), PPC_WORK, 0); \
} while (0)
#define md_clear_membase(inst,reg,offset) \
do { \
ppc_store_membase((inst), PPC_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); \
ppc_mov_reg_reg((inst), (reg), (basereg)); \
if(___value != 0) \
{ \
ppc_add_reg_imm((inst), (reg), (reg),
___value); \
} \
} while (0)
/*
* Move values between registers.
*/
#define md_mov_reg_reg(inst,dreg,sreg) \
ppc_mov_reg_reg((inst), (dreg), (sreg))
/*
* Set a register to a 0 or 1 value based on a condition.
*/
extern md_inst_ptr _md_ppc_setcc(md_inst_ptr inst, int reg,
int cond, int
invcond);
#define md_seteq_reg(inst,reg) \
do { (inst) = _md_ppc_setcc \
((inst), (reg), PPC_CC_EQ, PPC_CC_NE);
} while (0)
#define md_setne_reg(inst,reg) \
do { (inst) = _md_ppc_setcc \
((inst), (reg), PPC_CC_NE, PPC_CC_EQ);
} while (0)
#define md_setlt_reg(inst,reg) \
do { (inst) = _md_ppc_setcc \
((inst), (reg), PPC_CC_LT, PPC_CC_GE);
} while (0)
#define md_setle_reg(inst,reg) \
do { (inst) = _md_ppc_setcc \
((inst), (reg), PPC_CC_LE, PPC_CC_GT);
} while (0)
#define md_setgt_reg(inst,reg) \
do { (inst) = _md_ppc_setcc \
((inst), (reg), PPC_CC_GT, PPC_CC_LE);
} while (0)
#define md_setge_reg(inst,reg) \
do { (inst) = _md_ppc_setcc \
((inst), (reg), PPC_CC_GE, PPC_CC_LT);
} while (0)
/*
* Set a register to -1, 0, or 1 based on comparing two values.
*/
extern md_inst_ptr _md_ppc_setcmp(md_inst_ptr inst, int dreg);
#define md_cmp_reg_reg_word_32(inst,reg1,reg2) \
do { \
ppc_cmp_reg_reg((inst), PPC_CMP, (reg1),
(reg2)); \
(inst) = _md_ppc_setcmp((inst), (reg1)); \
} while (0)
#define md_ucmp_reg_reg_word_32(inst,reg1,reg2) \
do { \
ppc_cmp_reg_reg((inst), PPC_CMPL, (reg1),
(reg2)); \
(inst) = _md_ppc_setcmp((inst), (reg1)); \
} while (0)
/*
* Set the condition codes based on comparing two values.
*/
#define md_cmp_cc_reg_reg_word_32(inst,reg1,reg2) \
ppc_cmp_reg_reg((inst), PPC_CMP, (reg1), (reg2))
#define md_ucmp_cc_reg_reg_word_32(inst,reg1,reg2) \
ppc_cmp_reg_reg((inst), PPC_CMPL, (reg1), (reg2))
#define md_cmp_cc_reg_reg_word_native(inst,reg1,reg2) \
ppc_cmp_reg_reg((inst), PPC_CMP, (reg1), (reg2))
#define md_ucmp_cc_reg_reg_word_native(inst,reg1,reg2) \
ppc_cmp_reg_reg((inst), PPC_CMPL, (reg1), (reg2))
/*
* Test the contents of a register against NULL and set the
* condition codes based on the result.
*/
#define md_reg_is_null(inst,reg) \
ppc_cmp_reg_imm((inst), PPC_CMP, (reg), 0)
/*
* Test the contents of a register against 32-bit zero and set the
* condition codes based on the result.
*/
#define md_reg_is_zero(inst,reg) \
ppc_cmp_reg_imm((inst), PPC_CMP, (reg), 0)
/*
* Compare a 32-bit register against an immediate value and set
* the condition codes based on the result.
*/
#define md_cmp_reg_imm_word_32(inst,reg,imm) \
ppc_cmp_reg_imm((inst), PPC_CMPL, (reg), (int)(imm))
/*
* Output a branch to a location based on a condition. The actual
* jump offset will be filled in by a later "md_patch" call.
*/
#define md_branch_eq(inst) \
ppc_branch_imm((inst), PPC_CC_EQ, 0)
#define md_branch_ne(inst) \
ppc_branch_imm((inst), PPC_CC_NE, 0)
#define md_branch_lt(inst) \
ppc_branch_imm((inst), PPC_CC_LT, 0)
#define md_branch_le(inst) \
ppc_branch_imm((inst), PPC_CC_LE, 0)
#define md_branch_gt(inst) \
ppc_branch_imm((inst), PPC_CC_GT, 0)
#define md_branch_ge(inst) \
ppc_branch_imm((inst), PPC_CC_GE, 0)
#define md_branch_lt_un(inst) \
ppc_branch_imm((inst), PPC_CC_LT, 0)
#define md_branch_le_un(inst) \
ppc_branch_imm((inst), PPC_CC_LE, 0)
#define md_branch_gt_un(inst) \
ppc_branch_imm((inst), PPC_CC_GT, 0)
#define md_branch_ge_un(inst) \
ppc_branch_imm((inst), PPC_CC_GE, 0)
#define md_branch_cc(inst,cond) \
ppc_branch_imm((inst), (cond), 0)
/*
* Specific condition codes for "md_branch_cc".
*
* Note: the unsigned forms are obtained by performing a different
* kind of comparison just before the branch.
*/
#define MD_CC_EQ PPC_CC_EQ
#define MD_CC_NE PPC_CC_NE
#define MD_CC_LT PPC_CC_LT
#define MD_CC_LE PPC_CC_LE
#define MD_CC_GT PPC_CC_GT
#define MD_CC_GE PPC_CC_GE
#define MD_CC_LT_UN PPC_CC_LT
#define MD_CC_LE_UN PPC_CC_LE
#define MD_CC_GT_UN PPC_CC_GT
#define MD_CC_GE_UN PPC_CC_GE
/*
* Back-patch a branch instruction at "patch" to branch to "inst".
*/
#define md_patch(patch,inst) \
arm_patch((patch), (inst))
/*
* Check an array bounds value. "reg1" points to the array,
* and "reg2" is the array index to check. This will advance
* the pointer in "reg1" past the array bounds value.
*/
#define md_bounds_check(inst,reg1,reg2) \
do { \
arm_load_advance((inst), ARM_WORK, (reg1)); \
arm_test_reg_reg((inst), ARM_CMP, (reg2),
ARM_WORK); \
} while (0)
/*
* Load a 32-bit word value from an indexed array. "disp" is the offset
* to use to skip over the array bounds value. Some platforms may ignore
* "disp" if they advance the base pointer in "md_bounds_check".
*/
#define md_load_memindex_word_32(inst,reg,basereg,indexreg,disp) \
arm_load_memindex((inst), (reg), (basereg), (indexreg))
/*
* Load a native word value from an indexed array.
*/
#define md_load_memindex_word_native(inst,reg,basereg,indexreg,disp) \
arm_load_memindex((inst), (reg), (basereg), (indexreg))
/*
* Load a byte value from an indexed array.
*/
#define md_load_memindex_byte(inst,reg,basereg,indexreg,disp) \
arm_load_memindex_byte((inst), (reg), (basereg),
(indexreg))
/*
* Load a signed byte value from an indexed array.
*/
#define md_load_memindex_sbyte(inst,reg,basereg,indexreg,disp) \
arm_load_memindex_sbyte((inst), (reg), (basereg),
(indexreg))
/*
* Load a short value from an indexed array.
*/
#define md_load_memindex_short(inst,reg,basereg,indexreg,disp) \
arm_load_memindex_short((inst), (reg), (basereg),
(indexreg))
/*
* Load an unsigned short value from an indexed array.
*/
#define md_load_memindex_ushort(inst,reg,basereg,indexreg,disp) \
arm_load_memindex_ushort((inst), (reg), (basereg),
(indexreg))
/*
* Store a 32-bit word value into an indexed array.
*/
#define md_store_memindex_word_32(inst,reg,basereg,indexreg,disp) \
arm_store_memindex((inst), (reg), (basereg), (indexreg))
/*
* Store a native word value into an indexed array.
*/
#define md_store_memindex_word_native(inst,reg,basereg,indexreg,disp) \
arm_store_memindex((inst), (reg), (basereg), (indexreg))
/*
* Store a byte value into an indexed array.
*/
#define md_store_memindex_byte(inst,reg,basereg,indexreg,disp) \
arm_store_memindex_byte((inst), (reg), (basereg),
(indexreg))
/*
* Store a signed byte value into an indexed array.
*/
#define md_store_memindex_sbyte(inst,reg,basereg,indexreg,disp) \
arm_store_memindex_sbyte((inst), (reg), (basereg),
(indexreg))
/*
* Store a short value into an indexed array.
*/
#define md_store_memindex_short(inst,reg,basereg,indexreg,disp) \
arm_store_memindex_short((inst), (reg), (basereg),
(indexreg))
/*
* Store an unsigned short value into an indexed array.
*/
#define md_store_memindex_ushort(inst,reg,basereg,indexreg,disp) \
arm_store_memindex_ushort((inst), (reg), (basereg),
(indexreg))
#ifdef __cplusplus
};
#endif
#endif /* _ENGINE_MD_PPC_H */
--- NEW FILE ---
/*
* ppc_codegen.h - Code generation macros for the PPC processor.
*
* 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 _PPC_CODEGEN_H
#define _PPC_CODEGEN_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Register numbers.
*/
typedef enum
{
PPC_R0 = 0,
PPC_R1 = 1,
PPC_R2 = 2,
PPC_R3 = 3,
PPC_R4 = 4,
PPC_R5 = 5,
PPC_R6 = 6,
PPC_R7 = 7,
PPC_R8 = 8,
PPC_R9 = 9,
PPC_R10 = 10,
PPC_R11 = 11,
PPC_R12 = 12,
PPC_R13 = 13,
PPC_R14 = 14,
PPC_R15 = 15,
PPC_R16 = 16,
PPC_R17 = 17,
PPC_R18 = 18,
PPC_R19 = 19,
PPC_R20 = 20,
PPC_R21 = 21,
PPC_R22 = 22,
PPC_R23 = 23,
PPC_R24 = 24,
PPC_R25 = 25,
PPC_R26 = 26,
PPC_R27 = 27,
PPC_R28 = 28,
PPC_R29 = 29,
PPC_R30 = 30,
PPC_R31 = 31,
PPC_SP = PPC_R1,
PPC_WORK = PPC_R12,
} PPC_REG;
/*
* Floating-point register numbers.
*/
typedef enum
{
PPC_F0 = 0,
PPC_F1 = 1,
PPC_F2 = 2,
PPC_F3 = 3,
PPC_F4 = 4,
PPC_F5 = 5,
PPC_F6 = 6,
PPC_F7 = 7,
PPC_F8 = 8,
PPC_F9 = 9,
PPC_F10 = 10,
PPC_F11 = 11,
PPC_F12 = 12,
PPC_F13 = 13,
PPC_F14 = 14,
PPC_F15 = 15,
PPC_F16 = 16,
PPC_F17 = 17,
PPC_F18 = 18,
PPC_F19 = 19,
PPC_F20 = 20,
PPC_F21 = 21,
PPC_F22 = 22,
PPC_F23 = 23,
PPC_F24 = 24,
PPC_F25 = 25,
PPC_F26 = 26,
PPC_F27 = 27,
PPC_F28 = 28,
PPC_F29 = 29,
PPC_F30 = 30,
PPC_F31 = 31,
} PPC_FREG;
/*
* Condition codes for branch instructions.
*/
typedef enum
{
PPC_CC_BRFALSE = (4 << 5), /* Branch if
condition false */
PPC_CC_BRTRUE = (12 << 5), /* Branch if condition
true */
PPC_CC_EQ = PPC_CC_BRTRUE | 2, /* Equal */
PPC_CC_NE = PPC_CC_BRFALSE | 2, /* Not equal */
PPC_CC_LT = PPC_CC_BRTRUE | 0, /* Less than */
PPC_CC_LE = PPC_CC_BRFALSE | 1, /* Less than or equal */
PPC_CC_GT = PPC_CC_BRTRUE | 1, /* Greater than */
PPC_CC_GE = PPC_CC_BRFALSE | 0, /* Greater than or
equal */
} PPC_CC;
/*
* Arithmetic and logical operations.
*/
typedef enum
{
PPC_ADD = 266, /* Add */
PPC_ADDC = 10, /* Add with carry out */
PPC_ADDE = 138, /* Add with extended carry in */
PPC_SUBF = 40, /* Subtract from */
PPC_SUBFC = 8, /* Subtract from with carry out
*/
PPC_SUBFE = 136, /* Subtract from with extended
carry in */
PPC_MUL = 235, /* Multiply */
PPC_DIV = 491, /* Signed division */
PPC_DIV_UN = 459, /* Unsigned division */
PPC_AND = 28, /* And (sds) */
PPC_ANDC = 60, /* And with complement (sds) */
PPC_NAND = 476, /* Nand (sds) */
PPC_NOR = 124, /* Nor (sds) */
PPC_OR = 444, /* Or (sds) */
PPC_ORC = 412, /* Or with complement (sds) */
PPC_XOR = 316, /* Xor (sds) */
PPC_CMP = 0, /* Signed compare */
PPC_CMPL = 32, /* Unsigned (logical) compare */
PPC_NEG = 104, /* Negate */
PPC_SL = 24, /* Shift left (sds) */
PPC_SRA = 792, /* Shift right algebraic (sds)
*/
PPC_SR = 536, /* Shift right (sds) */
PPC_EXTSB = 954, /* Extend signed byte */
PPC_EXTSH = 922, /* Extend signed half word */
} PPC_OP;
/*
* Type for instruction pointers (word-based, not byte-based).
*/
typedef unsigned int *ppc_inst_ptr;
/*
* Perform an arithmetic or logical operation.
*/
#define ppc_alu_reg_dss(inst,opc,dreg,sreg1,sreg2) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)(sreg1)) << 16) | \
(((unsigned
int)(sreg2)) << 11) | \
(((unsigned int)(opc))
<< 1)); \
} while (0)
#define ppc_alu_reg_sds(inst,opc,dreg,sreg1,sreg2) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(sreg1)) << 21) | \
(((unsigned
int)(dreg)) << 16) | \
(((unsigned
int)(sreg2)) << 11) | \
(((unsigned int)(opc))
<< 1)); \
} while (0)
#define ppc_alu_reg_ds(inst,opc,dreg,sreg) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)(sreg)) << 16) | \
(((unsigned int)(opc))
<< 1)); \
} while (0)
#define ppc_alu_reg_sd(inst,opc,dreg,sreg) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(sreg)) << 21) | \
(((unsigned
int)(dreg)) << 16) | \
(((unsigned int)(opc))
<< 1)); \
} while (0)
/*
* Perform an arithmetic or logical operation and also set the
* condition codes.
*/
#define ppc_alu_cc_reg_dss(inst,opc,dreg,sreg1,sreg2) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)(sreg1)) << 16) | \
(((unsigned
int)(sreg2)) << 11) | \
(((unsigned int)(opc))
<< 1) | 1); \
} while (0)
#define ppc_alu_cc_reg_sds(inst,opc,dreg,sreg1,sreg2) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(sreg1)) << 21) | \
(((unsigned
int)(dreg)) << 16) | \
(((unsigned
int)(sreg2)) << 11) | \
(((unsigned int)(opc))
<< 1) | 1); \
} while (0)
#define ppc_alu_cc_reg_ds(inst,opc,dreg,sreg) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)(sreg)) << 16) | \
(((unsigned int)(opc))
<< 1) | 1); \
} while (0)
#define ppc_alu_cc_reg_sd(inst,opc,dreg,sreg) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(sreg)) << 21) | \
(((unsigned
int)(dreg)) << 16) | \
(((unsigned int)(opc))
<< 1) | 1); \
} while (0)
/*
* Perform a comparison on two registers. The result is put into CR0.
*/
#define ppc_cmp_reg_reg(inst,opc,reg1,reg2) \
do { \
*(inst)++ = ((31 << 26) | \
(((unsigned
int)(reg1)) << 16) | \
(((unsigned
int)(reg2)) << 11) | \
(((unsigned int)(opc))
<< 1)); \
} while (0)
/*
* Add an immediate value to a register. If "sreg" is R0, then this
* instruction acts like "ppc_mov_reg_imm" instead.
*/
#define ppc_add_reg_imm(inst,dreg,sreg,imm) \
do { \
int __value = (int)(imm); \
if(__value >= -0x8000 && __value <= 0x7FFF) \
{ \
*(inst)++ = ((14 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)(sreg)) << 16) | \
(((unsigned
int)(__value)) & 0xFFFF)); \
} \
else if((__value & 0xFFFF) == 0) \
{ \
*(inst)++ = ((15 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)(sreg)) << 16) | \
(((unsigned
int)(__value >> 16)) & 0xFFFF)); \
} \
else if((__value & 0x8000) == 0) \
{ \
*(inst)++ = ((14 << 26) | \
(((unsigned
int)PPC_WORK) << 21) | \
(((unsigned
int)(sreg)) << 16) | \
(((unsigned
int)(__value)) & 0xFFFF)); \
*(inst)++ = ((15 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)PPC_WORK) << 16) | \
(((unsigned
int)(__value >> 16)) & 0xFFFF)); \
} \
else \
{ \
*(inst)++ = ((14 << 26) | \
(((unsigned
int)PPC_WORK) << 21) | \
(((unsigned
int)(sreg)) << 16) | \
(((unsigned
int)(__value)) & 0xFFFF)); \
*(inst)++ = ((15 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)PPC_WORK) << 16) | \
(((unsigned
int)((__value >> 16) + 1)) \
& 0xFFFF)); \
} \
} while (0)
/*
* Subtract an immediate value from a register. "sreg" and "dreg"
* must not be R0.
*/
#define ppc_sub_reg_imm(inst,dreg,sreg,imm) \
do { \
ppc_add_reg_imm((inst), (dreg), (sreg),
-((int)(imm))); \
} while (0)
/*
* Move an immediate value into a register.
*/
#define ppc_mov_reg_imm(inst,reg,imm) \
do { \
ppc_add_reg_imm((inst), (reg), PPC_R0, (imm)); \
} while (0)
/*
* And an immediate value with a register.
*/
#define ppc_and_reg_imm(inst,dreg,sreg,imm) \
do { \
int __and_value = (int)(imm); \
if(__and_value >= 0 && __and_value <= 0xFFFF) \
{ \
*(inst)++ = ((28 << 26) | \
(((unsigned
int)(sreg)) << 21) | \
(((unsigned
int)(dreg)) << 16) | \
(((unsigned
int)(__and_value)) & 0xFFFF)); \
} \
else if((__and_value & 0xFFFF) == 0) \
{ \
*(inst)++ = ((29 << 26) | \
(((unsigned
int)(sreg)) << 21) | \
(((unsigned
int)(dreg)) << 16) | \
((((unsigned
int)(__and_value)) >> 16) & \
0xFFFF)); \
} \
else \
{ \
ppc_mov_reg_imm((inst), PPC_WORK,
__and_value); \
ppc_alu_reg_sds((inst), PPC_AND,
(dreg), \
(sreg),
PPC_WORK); \
} \
} while (0)
/*
* Move a value from one register to another.
*/
#define ppc_mov_reg_reg(inst,dreg,sreg) \
do { \
if((sreg) != PPC_R0) \
{ \
*(inst)++ = ((14 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)(sreg)) << 16)); \
} \
else \
{ \
*(inst)++ = ((14 << 26) | \
(((unsigned
int)(dreg)) << 21) | \
(((unsigned
int)PPC_R0) << 16)); \
ppc_alu_reg_dss((inst), PPC_ADD,
(dreg), (dreg), (sreg)); \
} \
} while (0)
/*
* Compare a register against an immediate value. The result ends up in CR0.
*/
#define ppc_cmp_reg_imm(inst,opc,reg,imm) \
do { \
int __value = (int)(imm); \
if((opc) == PPC_CMP) \
{ \
if(__value >= -0x8000 && __value <=
0x7FFF) \
{ \
*(inst)++ = ((11 << 26) | \
(((unsigned int)(reg)) << 16) | \
(((unsigned int)(__value)) & 0xFFFF)); \
} \
else \
{ \
ppc_mov_reg_imm((inst),
PPC_WORK, __value); \
ppc_cmp_reg_reg((inst),
PPC_CMP, (reg), PPC_WORK); \
} \
} \
else \
{ \
if(__value >= 0 && __value <= 0xFFFF) \
{ \
*(inst)++ = ((10 << 26) | \
(((unsigned int)(reg)) << 16) | \
((unsigned int)(__value))); \
} \
else \
{ \
ppc_mov_reg_imm((inst),
PPC_WORK, __value); \
ppc_cmp_reg_reg((inst),
PPC_CMPL, (reg), PPC_WORK); \
} \
} \
} while (0)
/*
* Jump to a particular address.
*/
#define ppc_jump(inst,target) \
do { \
/* TODO */ \
} while (0)
/*
* Jump to a particular address based on a condition.
*/
#define ppc_branch(inst,cond,target) \
do { \
/* TODO */ \
} while (0)
/*
* Load various sized values from a memory location defined by a base
* register and an offset.
*/
extern ppc_inst_ptr _md_ppc_get_ea(ppc_inst_ptr inst, int basereg, int offset);
#define ppc_membase_common(inst,reg,basereg,offset,opc) \
do { \
int __ld_offset = (int)(offset); \
if(__ld_offset >= -0x8000 && __ld_offset <=
0x7FFF) \
{ \
*(inst)++ = (((opc) << 26) | \
(((unsigned
int)(reg)) << 21) | \
(((unsigned
int)(basereg)) << 16) | \
(((unsigned
int)(__ld_offset)) & 0xFFFF)); \
} \
else \
{ \
(inst) = _md_ppc_get_ea((inst),
(basereg), __ld_offset); \
*(inst)++ = (((opc) << 26) | \
(((unsigned
int)(reg)) << 21) | \
(((unsigned
int)PPC_WORK) << 16)); \
} \
} while (0)
#define ppc_load_membase(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
32)
#define ppc_load_membase_byte(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
34)
#define ppc_load_membase_sbyte(inst,reg,basereg,offset) \
do { \
ppc_membase_common((inst), (reg), (basereg),
(offset), 34); \
ppc_alu_reg_sd((inst), PPC_EXTSB, (reg),
(reg)); \
} while (0)
#define ppc_load_membase_short(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
42)
#define ppc_load_membase_ushort(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
40)
/*
* Store values of various sizes to a memory location defined by a
* base register plus an offset.
*/
#define ppc_store_membase(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
36)
#define ppc_store_membase_byte(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
38)
#define ppc_store_membase_sbyte(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
38)
#define ppc_store_membase_short(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
44)
#define ppc_store_membase_ushort(inst,reg,basereg,offset) \
ppc_membase_common((inst), (reg), (basereg), (offset),
44)
/*
* Push the contents of a word register onto the stack.
*/
#define ppc_push_reg(inst,reg) \
ppc_membase_common((inst), (reg), PPC_SP, -4, 37)
/*
* Pop the contents of a word register from the stack.
*/
#define ppc_pop_reg(inst,reg) \
do { \
ppc_membase_common((inst), (reg), PPC_SP, 0,
32); \
ppc_add_reg_imm((inst), PPC_SP, PPC_SP, 4); \
} while (0)
#ifdef __cplusplus
};
#endif
#endif /* _PPC_CODEGEN_H */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnet/engine md_ppc.h, NONE, 1.1 ppc_codegen.h, NONE, 1.1,
Rhys Weatherley <address@hidden> <=
- Prev by Date:
[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Runtime/Remoting/Messaging Header.cs, 1.2, 1.3 HeaderHandler.cs, 1.1, 1.2 IMessage.cs, 1.1, 1.2 IMethodCallMessage.cs, 1.1, 1.2 IMethodMessage.cs, 1.1, 1.2 IMethodReturnMessage.cs, 1.1, 1.2 IRemotingFormatter.cs, 1.1, 1.2 ISerializationRootObject.cs, 1.1, 1.2 LogicalCallContext.cs, 1.2, 1.3
- Next by Date:
[Dotgnu-pnet-commits] CVS: pnet ChangeLog,1.2632,1.2633
- Previous by thread:
[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Runtime/Remoting/Messaging Header.cs, 1.2, 1.3 HeaderHandler.cs, 1.1, 1.2 IMessage.cs, 1.1, 1.2 IMethodCallMessage.cs, 1.1, 1.2 IMethodMessage.cs, 1.1, 1.2 IMethodReturnMessage.cs, 1.1, 1.2 IRemotingFormatter.cs, 1.1, 1.2 ISerializationRootObject.cs, 1.1, 1.2 LogicalCallContext.cs, 1.2, 1.3
- Next by thread:
[Dotgnu-pnet-commits] CVS: pnet ChangeLog,1.2632,1.2633
- Index(es):