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_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 */





reply via email to

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