tcg-target.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 660 行 · 第 1/2 页

C
660
字号
/* * Tiny Code Generator for QEMU * * Copyright (c) 2008 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {    "%g0",    "%g1",    "%g2",    "%g3",    "%g4",    "%g5",    "%g6",    "%g7",    "%o0",    "%o1",    "%o2",    "%o3",    "%o4",    "%o5",    "%o6",    "%o7",    "%l0",    "%l1",    "%l2",    "%l3",    "%l4",    "%l5",    "%l6",    "%l7",    "%i0",    "%i1",    "%i2",    "%i3",    "%i4",    "%i5",    "%i6",    "%i7",};static const int tcg_target_reg_alloc_order[] = {    TCG_REG_L0,    TCG_REG_L1,    TCG_REG_L2,    TCG_REG_L3,    TCG_REG_L4,    TCG_REG_L5,    TCG_REG_L6,    TCG_REG_L7,    TCG_REG_I0,    TCG_REG_I1,    TCG_REG_I2,    TCG_REG_I3,    TCG_REG_I4,};static const int tcg_target_call_iarg_regs[6] = {    TCG_REG_O0,    TCG_REG_O1,    TCG_REG_O2,    TCG_REG_O3,    TCG_REG_O4,    TCG_REG_O5,};static const int tcg_target_call_oarg_regs[2] = {    TCG_REG_O0,    TCG_REG_O1,};static void patch_reloc(uint8_t *code_ptr, int type,                        tcg_target_long value, tcg_target_long addend){    value += addend;    switch (type) {    case R_SPARC_32:        if (value != (uint32_t)value)            tcg_abort();        *(uint32_t *)code_ptr = value;        break;    default:        tcg_abort();    }}/* maximum number of register used for input function arguments */static inline int tcg_target_get_call_iarg_regs_count(int flags){    return 6;}/* parse target specific constraints */static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str){    const char *ct_str;    ct_str = *pct_str;    switch (ct_str[0]) {    case 'r':    case 'L': /* qemu_ld/st constraint */        ct->ct |= TCG_CT_REG;        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);        break;    case 'I':        ct->ct |= TCG_CT_CONST_S11;        break;    case 'J':        ct->ct |= TCG_CT_CONST_S13;        break;    default:        return -1;    }    ct_str++;    *pct_str = ct_str;    return 0;}#define ABS(x) ((x) < 0? -(x) : (x))/* test if a constant matches the constraint */static inline int tcg_target_const_match(tcg_target_long val,                                         const TCGArgConstraint *arg_ct){    int ct;    ct = arg_ct->ct;    if (ct & TCG_CT_CONST)        return 1;    else if ((ct & TCG_CT_CONST_S11) && ABS(val) == (ABS(val) & 0x3ff))        return 1;    else if ((ct & TCG_CT_CONST_S13) && ABS(val) == (ABS(val) & 0xfff))        return 1;    else        return 0;}#define INSN_OP(x)  ((x) << 30)#define INSN_OP2(x) ((x) << 22)#define INSN_OP3(x) ((x) << 19)#define INSN_OPF(x) ((x) << 5)#define INSN_RD(x)  ((x) << 25)#define INSN_RS1(x) ((x) << 14)#define INSN_RS2(x) (x)#define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))#define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)#define INSN_COND(x, a) (((x) << 25) | ((a) << 29))#define COND_A     0x8#define BA         (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))#define ARITH_ADD  (INSN_OP(2) | INSN_OP3(0x00))#define ARITH_AND  (INSN_OP(2) | INSN_OP3(0x01))#define ARITH_OR   (INSN_OP(2) | INSN_OP3(0x02))#define ARITH_XOR  (INSN_OP(2) | INSN_OP3(0x03))#define ARITH_SUB  (INSN_OP(2) | INSN_OP3(0x08))#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10))#define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))#define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))#define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))#define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))#define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))#define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))#define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))#define SHIFT_SLL  (INSN_OP(2) | INSN_OP3(0x25))#define SHIFT_SRL  (INSN_OP(2) | INSN_OP3(0x26))#define SHIFT_SRA  (INSN_OP(2) | INSN_OP3(0x27))#define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))#define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))#define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))#define WRY        (INSN_OP(2) | INSN_OP3(0x30))#define JMPL       (INSN_OP(2) | INSN_OP3(0x38))#define SAVE       (INSN_OP(2) | INSN_OP3(0x3c))#define RESTORE    (INSN_OP(2) | INSN_OP3(0x3d))#define SETHI      (INSN_OP(0) | INSN_OP2(0x4))#define CALL       INSN_OP(1)#define LDUB       (INSN_OP(3) | INSN_OP3(0x01))#define LDSB       (INSN_OP(3) | INSN_OP3(0x09))#define LDUH       (INSN_OP(3) | INSN_OP3(0x02))#define LDSH       (INSN_OP(3) | INSN_OP3(0x0a))#define LDUW       (INSN_OP(3) | INSN_OP3(0x00))#define LDSW       (INSN_OP(3) | INSN_OP3(0x08))#define LDX        (INSN_OP(3) | INSN_OP3(0x0b))#define STB        (INSN_OP(3) | INSN_OP3(0x05))#define STH        (INSN_OP(3) | INSN_OP3(0x06))#define STW        (INSN_OP(3) | INSN_OP3(0x04))#define STX        (INSN_OP(3) | INSN_OP3(0x0e))static inline void tcg_out_mov(TCGContext *s, int ret, int arg){    tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(arg) |              INSN_RS2(TCG_REG_G0));}static inline void tcg_out_movi(TCGContext *s, TCGType type,                                int ret, tcg_target_long arg){#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)    if (arg != (arg & 0xffffffff))        fprintf(stderr, "unimplemented %s with constant %ld\n", __func__, arg);#endif    if (arg == (arg & 0xfff))        tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(TCG_REG_G0) |                  INSN_IMM13(arg));    else {        tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10));        if (arg & 0x3ff)            tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(ret) |                      INSN_IMM13(arg & 0x3ff));    }}static inline void tcg_out_ld_raw(TCGContext *s, int ret,                                  tcg_target_long arg){    tcg_out32(s, SETHI | INSN_RD(ret) | (((uint32_t)arg & 0xfffffc00) >> 10));    tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |              INSN_IMM13(arg & 0x3ff));}static inline void tcg_out_ld_ptr(TCGContext *s, int ret,                                  tcg_target_long arg){#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)    if (arg != (arg & 0xffffffff))        fprintf(stderr, "unimplemented %s with offset %ld\n", __func__, arg);    if (arg != (arg & 0xfff))        tcg_out32(s, SETHI | INSN_RD(ret) | (((uint32_t)arg & 0xfffffc00) >> 10));    tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |              INSN_IMM13(arg & 0x3ff));#else    tcg_out_ld_raw(s, ret, arg);#endif}static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op){    if (offset == (offset & 0xfff))        tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |                  INSN_IMM13(offset));    else        fprintf(stderr, "unimplemented %s with offset %d\n", __func__, offset);}static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,                              int arg1, tcg_target_long arg2){    fprintf(stderr, "unimplemented %s\n", __func__);}static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,                              int arg1, tcg_target_long arg2){    fprintf(stderr, "unimplemented %s\n", __func__);}static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,                                 int op){    tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |              INSN_RS2(rs2));}static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1, int offset,                                  int op){    tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |              INSN_IMM13(offset));}static inline void tcg_out_sety(TCGContext *s, tcg_target_long val){    if (val == 0 || val == -1)        tcg_out32(s, WRY | INSN_IMM13(val));    else        fprintf(stderr, "unimplemented sety %ld\n", (long)val);}static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val){    if (val != 0) {        if (val == (val & 0xfff))            tcg_out_arithi(s, reg, reg, val, ARITH_ADD);        else            fprintf(stderr, "unimplemented addi %ld\n", (long)val);    }}static inline void tcg_out_nop(TCGContext *s){    tcg_out32(s, SETHI | INSN_RD(TCG_REG_G0) | 0);}static inline void tcg_target_prologue(TCGContext *s){    tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |              INSN_IMM13(-TCG_TARGET_STACK_MINFRAME));}static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,                              const int *const_args){    int c;    switch (opc) {    case INDEX_op_exit_tb:        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]);        tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I7) |                  INSN_IMM13(8));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?