From patchwork Sat Dec 5 15:23:43 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: identifier scorpio X-Patchwork-Id: 40401 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id AE098B7BE0 for ; Sun, 6 Dec 2009 02:25:43 +1100 (EST) Received: from localhost ([127.0.0.1]:54419 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NGwVp-0007a2-Q6 for incoming@patchwork.ozlabs.org; Sat, 05 Dec 2009 10:25:33 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NGwUM-0007Jm-7Q for qemu-devel@nongnu.org; Sat, 05 Dec 2009 10:24:02 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NGwUH-0007Hx-6a for qemu-devel@nongnu.org; Sat, 05 Dec 2009 10:24:01 -0500 Received: from [199.232.76.173] (port=41206 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NGwUG-0007Hs-Ty for qemu-devel@nongnu.org; Sat, 05 Dec 2009 10:23:57 -0500 Received: from web15904.mail.cnb.yahoo.com ([202.165.103.49]:28888) by monty-python.gnu.org with smtp (Exim 4.60) (envelope-from ) id 1NGwUD-0007aP-Bh for qemu-devel@nongnu.org; Sat, 05 Dec 2009 10:23:56 -0500 Received: (qmail 6705 invoked by uid 60001); 5 Dec 2009 15:23:44 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com.cn; s=s1024; t=1260026624; bh=6djGM+J3PdrT3IAvlP6gjNNNrA7LtcTxIEr31UmE5N0=; h=Message-ID:X-YMail-OSG:Received:X-Mailer:Date:From:Subject:To:MIME-Version:Content-Type; b=1Eq6dd51V9xYGKHLC6mQ/widAHTZ7D3uS0nKU/DQqDQWc+XT/QAQ4uXA1g3I14udMfbzSo5GHs2ixn3ujUdxeWOCqJ8mVaBERS5lxy+Mip+9BZLT8S0RQTgWvaOxaJWKl2PL2XzVDcbOkiGZzoMb2XIU8hAB5jS1RCUwx2ClRSI= DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com.cn; h=Message-ID:X-YMail-OSG:Received:X-Mailer:Date:From:Subject:To:MIME-Version:Content-Type; b=JXAohzrwEX4oeA6x7NR+r9YOqCo+y0rcsp5fCLR9C4j8rYONsmIZBlGdZqH9hz7yzwKEYuTjhiiXRvhixKZpchPRXiX0rAXWDwitzJePAPR+abWoxwCMcFslfhy0FtG4L1dH8U47/nA3o/GWtl08EXALL2bvH197KnGULKeZYuI=; Message-ID: <245943.6550.qm@web15904.mail.cnb.yahoo.com> X-YMail-OSG: oyoCp14VM1meWW2wQsqwLxmP9De2CYIJMjzo2C13PHLgYFa.K7qiLd9qIHDyebgSPyXMBoyTM1etBWQnJWw1k70STpONj.ef3UXMCJzenUX6nak6IZ3n6B7SX13QQCsJ.WJJzWMtQwKLx5IARZ3wHAFu6ydPw5wSUls9tMNIfQ8Z_BvCThJPRn_Lj4emoxYF78mYWJjArTOgNSjbPW.IRzFZMiGL10Y1sFk.AQ5FBC1.nxFVt1JkYcfQjS0.2ebp5T2tw7OwKgdSlg-- Received: from [115.60.159.170] by web15904.mail.cnb.yahoo.com via HTTP; Sat, 05 Dec 2009 23:23:43 CST X-Mailer: YahooMailClassic/9.0.19 YahooMailWebService/0.8.100.260964 Date: Sat, 5 Dec 2009 23:23:43 +0800 (CST) From: identifier scorpio To: qemu-devel@nongnu.org MIME-Version: 1.0 X-detected-operating-system: by monty-python.gnu.org: FreeBSD 6.x (1) Subject: [Qemu-devel] about porting qemu to alpha platform X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Hello all!   I'm trying to port qemu to alpha platform, and my working environment is  an alpha xp1000 workstation (21264) that is running debian 5.   I'v got some progress, and now it can run PC BIOS, and can launch linux 2.6  using the linux-0.2.img given by qemu web-site. But linux got a panic when  mounting root fs. Surely there must be something wrong in my code, or something  out of my knowledge is omitted. below is my testing command line: qemu -hda /opt/linux-0.2.img -m 256 -curses   I'v tried to find the bugs for a couple of painful days, including studying  qemu.log, running test-i386 benchmark (all the basic x86 insn passed test, but test-i386 stops at test_exception(), reporing uncaught signal 10, to be honestly, i don't know the real reason). I'v not debugged the linux kernel running in qemu with gdb yet,  it seems to be a terrible job.   So, I post the patch and hope someone may give me some help or suggestions to find the fault, or tell me that am I doing the right thing? TIA.   BTW, I know that alpha is disappearing, but I really hope qemu can run on it. Dong Weiyu. ___________________________________________________________ 好玩贺卡等你发,邮箱贺卡全新上线! http://card.mail.cn.yahoo.com/ diff -urN qemu-0.10.0/cpu-all.h qemu-0.10.0.alpha/cpu-all.h --- qemu-0.10.0/cpu-all.h    2009-03-04 14:54:45.000000000 -0800 +++ qemu-0.10.0.alpha/cpu-all.h    2009-10-25 23:13:53.000000000 -0700 @@ -22,7 +22,7 @@    #include "qemu-common.h"   -#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) +#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__alpha__)  #define WORDS_ALIGNED  #endif   diff -urN qemu-0.10.0/tcg/alpha/tcg-target.c qemu-0.10.0.alpha/tcg/alpha/tcg-target.c --- qemu-0.10.0/tcg/alpha/tcg-target.c    1969-12-31 16:00:00.000000000 -0800 +++ qemu-0.10.0.alpha/tcg/alpha/tcg-target.c    2009-11-26 05:13:41.000000000 -0800 @@ -0,0 +1,1477 @@ +/* + * 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. + */ + +/* + * code review modification: + * 1. $15 is deleted from reserved register set and add to tcg_target_reg_alloc_order[] + * 2. $25 is deleted from tcg_target_reg_alloc_order[] + * 3. callee-clobbered register set bug fixed + * 4. tcg_out_ld/st bug fixed + * 5. translation of INDEX_op_exit_tb bug fixed + * 6. translation of INDEX_op_goto_tb bug fixed + * 7. tcg_out_brcond() bug fixed + * 8. patch_reloc() rewritten + * 9. qemu_ld/st() bug fixed + * 10. mul() ??? + * 11. be careful about register order, like tcg_out_mov() + * 12. remove INDEX_op_mov(i)_i32/i64 from tcg_out_op(), they are already implemented in tcg.c + * 13. icache flush not implemented ??? +*/ + +#ifndef NDEBUG +static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { +    "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", +    "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", +    "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", +    "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31", +}; +#endif + +/*  + * $26 ~ $31 are special, reserved,  + * and $25 is deliberately reserved for jcc operation + * and $0 is usually used for return function result, better allocate it later + * and $15 is used for cpu_env pointer, allocate it at last +*/ +static const int tcg_target_reg_alloc_order[] = { +    TCG_REG_1, TCG_REG_2, TCG_REG_3, TCG_REG_4, TCG_REG_5, TCG_REG_6, +    TCG_REG_7, TCG_REG_8, TCG_REG_22, TCG_REG_23, TCG_REG_24, +    TCG_REG_9, TCG_REG_10, TCG_REG_11, TCG_REG_12, TCG_REG_13, TCG_REG_14, +    TCG_REG_16, TCG_REG_17, TCG_REG_18, TCG_REG_19, TCG_REG_20, TCG_REG_21, +    TCG_REG_0, TCG_REG_15 +}; + +/* + * according to alpha calling convention, these 6 registers are used for  + * function parameter passing. if function has more than 6 parameters, remained + * ones are stored on stack. +*/ +static const int tcg_target_call_iarg_regs[6] = {  +    TCG_REG_16, TCG_REG_17, TCG_REG_18, TCG_REG_19, TCG_REG_20, TCG_REG_21 +    }; + +/* + * according to alpha calling convention, $0 is used for returning function result. +*/ +static const int tcg_target_call_oarg_regs[1] = { TCG_REG_0 }; + +/* + * save the address of TB's epilogue. +*/ +static uint8_t *tb_ret_addr; + +/*  + * op-code and func-code for jump insn  +*/ +#define CONTROL_CALL    0x01A +#define CONTROL_RET        0x01A +#define CONTROL_JMP        0x01A + +#define FUNC_JMP        0x00 +#define FUNC_CALL        0x01 +#define FUNC_RET        0x02 + +#define CONTROL_BR        0x30 +#define CONTROL_BSR        0x34 +#define CONTROL_BEQ        0x39 +#define CONTROL_BNE        0x3D +#define CONTROL_BLT        0x3A +#define CONTROL_BLE        0x3B +#define CONTROL_BGT        0x3F +#define CONTROL_BGE        0x3E +#define CONTROL_BLBC    0x38 +#define CONTROL_BLBS    0x3C + +#define ALPHA_ARITH        0x10 + +#define ARITH_ADDL        0x00 +#define ARITH_SUBL        0x09 +#define ARITH_ADDQ        0x20 +#define ARITH_SUBQ        0x29 +#define ARITH_CMPEQ        0x2D +#define ARITH_CMPLT        0x4D +#define ARITH_CMPLE        0x6D +#define ARITH_CMPULT    0x1D +#define ARITH_CMPULE    0x3D + +#define ALPHA_MUL        0x13 + +#define ARITH_MULL        0x00 +#define ARITH_MULQ        0x20 + +#define ALPHA_LOGIC        0x11 + +#define ARITH_AND        0x00 +#define ARITH_BIC        0x08 +#define ARITH_BIS        0x20 +#define ARITH_ORNOT        0x28 +#define ARITH_XOR        0x40 +#define ARITH_EQV        0x48 + +#define ALPHA_SHIFT        0x12 + +#define ARITH_SLL        0x39 +#define ARITH_SRL        0x34 +#define ARITH_SRA        0x3C + +#define ALPHA_SEXT        0x1C + +#define ARITH_SEXTB        0x00 +#define ARITH_SEXTW        0x01 + +#define ALPHA_LDA        0x08 +#define ALPHA_LDAH        0x09 +#define ALPHA_LDBU        0x0A +#define ALPHA_LDWU        0x0C +#define ALPHA_LDL        0x28 +#define ALPHA_LDQ        0x29 +#define ALPHA_STB        0x0E +#define ALPHA_STW        0x0D +#define ALPHA_STL        0x2C +#define ALPHA_STQ        0x2D + +/* + * return the # of regs used for parameter passing on procedure calling. + * note that alpha use $16~$21 to transfer the first 6 paramenters of a procedure. +*/ +static inline int tcg_target_get_call_iarg_regs_count(int flags) +{ +    return 6; +} + +/* + * given constraint, return available register set. this function is called once + * for each op at qemu's initialization stage. +*/ +static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) +{ +    const char *ct_str = *pct_str; + +    switch(ct_str[0])  +    { +    case 'r': +        /* constaint 'r' means any register is okay */ +        ct->ct |= TCG_CT_REG; +        tcg_regset_set32(ct->u.regs, 0, 0xffffffff); +        break; + +    case 'L': +        /*  +        * constranit 'L' is used for qemu_ld/st, which has 2 meanings: +        * 1st, we the argument need to be allocated a register. +        * 2nd, we should reserve some registers that belong to caller-clobbered  +        * list for qemu_ld/st local usage, so these registers must not be  +        * allocated to the argument that the 'L' constraint is describing. +        * +        * note that op qemu_ld/st has the TCG_OPF_CALL_CLOBBER flag, and  +        * tcg will free all callee-clobbered registers before generate target +        * insn for qemu_ld/st, so we can use these register directly without +        * warrying about destroying their content. +        */ +        ct->ct |= TCG_CT_REG; +        tcg_regset_set32(ct->u.regs, 0, 0xffffffff); +        tcg_regset_reset_reg(ct->u.regs, TCG_REG_0); +        tcg_regset_reset_reg(ct->u.regs, TCG_REG_16); +        tcg_regset_reset_reg(ct->u.regs, TCG_REG_17); +        tcg_regset_reset_reg(ct->u.regs, TCG_REG_18); +        break; + +    default: +        return -1; +    } + +    ct_str++; +    *pct_str = ct_str; +    return 0; +} + +/* + * whether op's input argument may use constant  +*/ +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 +        return 0; +} + +/* + * construct insn with following format.  + * (suitable for conditional branch insn) + * + * 31        26 25    21 20                            0 + * ------------------------------------------------------ + * |   OpCode  |   Ra   |              Disp             | + * ------------------------------------------------------ +*/ +static inline void tcg_out_inst2(TCGContext *s, int Opcode, int Ra, int Disp) +{ +    uint32_t v; +      +    v = ( ( Opcode & 0x3f ) << 26  ) +       | ( ( Ra & 0x1f ) << 21 ) +       | ( Disp & 0x1fffff) ; + +    tcg_out32(s, v);      +} + +/* + * construct insn with following format.  + * (used for ld/st or lda/ldah insn) + * + * 31        26 25    21 20    16 15                   0 + * ------------------------------------------------------ + * |   OpCode  |   Ra   |   Rb   |     Disp             | + * ------------------------------------------------------ +*/ +static inline void tcg_out_inst3_disp(TCGContext *s, int Opcode, int Ra, int Rb, int Disp) +{ +    uint32_t v; +      +    v = ( ( Opcode & 0x3f ) << 26  ) +       | ( ( Ra & 0x1f ) << 21 ) +       | ( ( Rb & 0x1f ) << 16 ) +       | ( Disp & 0xffff) ; + +    tcg_out32(s, v);      +} + +/* + * construct insn with following format.  + * (used for jmp insn) + * + * 31        26 25    21 20    16 15                   0 + * ------------------------------------------------------ + * |   OpCode  |   Ra   |   Rb   | Func |    Rsvd       | + * ------------------------------------------------------ +*/ +static inline void tcg_out_inst3_func(TCGContext *s, int Opcode, int Ra, int Rb, int Func, int Disp) +{ +    uint32_t v; +      +    v = ( ( Opcode & 0x3f ) << 26  ) +       | ( ( Ra & 0x1f ) << 21 ) +       | ( ( Rb & 0x1f ) << 16 ) +       | ( ( Func & 0x3 ) << 14 ) +       | ( Disp & 0x3fff) ; + +    tcg_out32(s, v);      +} + +/* + * construct insn with following format.  + * (used for operate insn) + * + *                                        1 + * 31        26 25    21 20    16 15 13 2 11     5 4   0 + * ------------------------------------------------------ + * |   OpCode  |   Ra   |   Rb   | SBZ |0|  Func  | Rc  | + * ------------------------------------------------------ +*/ +static inline void tcg_out_inst4(TCGContext *s, int Opcode, int Ra, int Rb, int Func, int Rc) +{ +    uint32_t v; + +    v = ( (Opcode & 0x3f) << 26  ) +       | ( ( Ra & 0x1f ) << 21 ) +       | ( ( Rb & 0x1f ) << 16 ) +       | ( ( Func & 0x7f ) << 5 ) +       | ( Rc & 0x1f ) ; + +    tcg_out32(s, v);      +} + +/* + * construct insn with following format.  + * (used for operate insn with immediate) + * + *                                        1 + * 31        26 25    21 20          13 2 11     5 4   0 + * ------------------------------------------------------ + * |   OpCode  |   Ra   |     LIT      |1|  Func  | Rc  | + * ------------------------------------------------------ +*/ +static inline void tcg_out_inst4i(TCGContext *s, int Opcode, int Ra, int Lit, int Func, int Rc) +{ +    uint32_t v; + +    v = ( (Opcode & 0x3f) << 26  ) +       | ( ( Ra & 0x1f ) << 21 ) +       | ( ( Lit & 0xff ) << 13 ) +       | ( ( Func & 0x7f ) << 5 ) +       | ( 1 << 12 ) +       | ( Rc & 0x1f ) ; + +    tcg_out32(s, v);      +} + +/* + * mov from a reg to another +*/ +static inline void tcg_out_mov(TCGContext *s, int Rc, int Rb) +{   +    if ( Rb != Rc ) { +        tcg_out_inst4(s, ALPHA_LOGIC, TCG_REG_31, Rb, ARITH_BIS, Rc);        // bis $31, Rb, Rc +    } +} + +/* + * mov a 64-bit immediate 'arg' to regsiter 'Ra', this function will + * generate fixed length (5 insns, 20 bytes) of target insn sequence. +*/ +static inline void tcg_out_movi_fixl( \ +    TCGContext *s, TCGType type, int Ra, tcg_target_long arg) +{ +    if( arg & ((tcg_target_ulong)0x800000000000) ) +        tcg_out_inst3_disp(s, ALPHA_LDAH, Ra, TCG_REG_31, (arg>>48)+1 ); +    else +        tcg_out_inst3_disp(s, ALPHA_LDAH, Ra, TCG_REG_31, arg>>48 );        // ldah Ra, arg<63:48>($31) +      +    if( arg & ((tcg_target_ulong)0x80000000) ) { +        tcg_out_inst3_disp(s, ALPHA_LDA, Ra, Ra, (arg>>32)+1 );  +    } +    else +        tcg_out_inst3_disp(s, ALPHA_LDA, Ra, Ra, arg>>32 );                    // lda Ra, arg<47:32>(Ra) +      +    tcg_out_inst4i(s, ALPHA_SHIFT, Ra, 32, ARITH_SLL, Ra);                    // sll Ra, 32, Ra +      +    if( arg & ((tcg_target_ulong)0x8000) ) +        tcg_out_inst3_disp(s, ALPHA_LDAH, Ra, Ra, (arg>>16)+1 );  +    else +        tcg_out_inst3_disp(s, ALPHA_LDAH, Ra, Ra, arg>>16 );                // ldah Ra, arg<31:16>(Ra) +      +    tcg_out_inst3_disp(s, ALPHA_LDA, Ra, Ra, arg );                            // lda Ra, arg<15:0>(Ra) +} + +/* + * mov 64-bit immediate 'arg' to regsiter 'Ra'. this function will + * generate variable length of target insn sequence. +*/ +static inline void tcg_out_movi( \ +    TCGContext *s, TCGType type, int Ra, tcg_target_long arg) +{ +    if (arg == 0) { +        tcg_out_inst4(s, ALPHA_LOGIC, Ra, Ra, ARITH_XOR, Ra);                // xor Ra, Ra, Ra +    } +    else if( arg == (int16_t)arg ) { +        tcg_out_inst3_disp(s, ALPHA_LDA, Ra, TCG_REG_31, arg );                // lda Ra, arg<15:0>($31) +    } +    else if( arg == (int32_t)arg ) { +        if( arg & (1<<15) ) { +            tcg_out_inst3_disp(s, ALPHA_LDAH, Ra, TCG_REG_31, (arg>>16)+1); +        } else { +            tcg_out_inst3_disp(s, ALPHA_LDAH, Ra, TCG_REG_31, arg>>16);        // ldah Ra, arg<31:16>($31) +        } +        tcg_out_inst3_disp(s, ALPHA_LDA, Ra, Ra, arg );                        // lda Ra, arg<15:0>(Ra) +    } else { +        /* use the most complex style of movement */ +        tcg_out_movi_fixl(s, type, Ra, arg); +    } +} + +/* + * load value in disp(Rb) to Ra. +*/ +static inline void tcg_out_ld( \ +    TCGContext *s, TCGType type, int Ra, int Rb, tcg_target_long disp) +{ +    int Opcode; +     +    if( type == TCG_TYPE_I32) { +        Opcode = ALPHA_LDL; +    } else { +        Opcode = ALPHA_LDQ; +    } +      +    if( disp != (int16_t)disp ) { +        /* disp cannot be stored in insn directly */ +        tcg_out_movi(s, type, TMP_REG, disp);      +        tcg_out_inst4(s, ALPHA_ARITH, Rb, TMP_REG, ARITH_ADDQ, TMP_REG);        // addq Rb, TMP_REG, TMP_REG +        tcg_out_inst3_disp(s, Opcode, Ra, TMP_REG, 0);                        // ldx Ra, 0(TMP_REG) +    } +    else +        tcg_out_inst3_disp(s, Opcode, Ra, Rb, disp);                        // ldx Ra, disp(Rb) +} + +/* + * store value in Ra to disp(Rb). +*/ +static inline void tcg_out_st( \ +    TCGContext *s, TCGType type, int Ra, int Rb, tcg_target_long disp) +{ +    int Opcode; + +    if( type == TCG_TYPE_I32) { +        Opcode = ALPHA_STL; +    } else { +        Opcode = ALPHA_STQ; +    } + +    if( disp != (int16_t)disp ) { +        /* disp cannot be stored in insn directly */ +        tcg_out_movi(s, type, TMP_REG, disp); +        tcg_out_inst4(s, ALPHA_ARITH, Rb, TMP_REG, ARITH_ADDQ, TMP_REG);    // addq Rb, TMP_REG, TMP_REG +        tcg_out_inst3_disp(s, Opcode, Ra, TMP_REG, 0);                        // stx Ra, 0(TMP_REG) +    } +    else +        tcg_out_inst3_disp(s, Opcode, Ra, Rb, disp);                        // stx Ra, disp(Rb) +} + +/* + * generate arithmatic instruction with immediate. Ra is used as both + * input and output, and val is used as another input. +*/ +static inline void tgen_arithi( \ +    TCGContext *s, int Opcode, int Func, int Ra, tcg_target_long val) +{ +    if (val == (uint8_t)val) { +        tcg_out_inst4i(s, Opcode, Ra, val, Func, Ra);                        // arithi Ra, #b, Ra +    } else { +        tcg_out_movi(s, TCG_TYPE_I64, TMP_REG, val); +        tcg_out_inst4(s, Opcode, Ra, TMP_REG, Func, Ra);                    // arithi Ra, TMP_REG, Ra +    } +} + +/* + * generate addq instruction with immediate. +*/ +static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) +{ +    if (val != 0) +        tgen_arithi(s, ALPHA_ARITH, ARITH_ADDQ, reg, val); +} + +/* + * generate insn to push reg onto stack. +*/ +static inline void tcg_out_push(TCGContext *s, int reg) +{ +    tcg_out_inst4i(s, ALPHA_ARITH, TCG_REG_30, 8, ARITH_SUBQ, TCG_REG_30); +    tcg_out_inst3_disp(s, ALPHA_STQ, reg, TCG_REG_30, 0); +} + +/* + * generate insn to pop value from stack to reg. +*/ +static inline void tcg_out_pop(TCGContext *s, int reg) +{ +    tcg_out_inst3_disp(s, ALPHA_LDQ, reg, TCG_REG_30, 0); +    tcg_out_inst4i(s, ALPHA_ARITH, TCG_REG_30, 8, ARITH_ADDQ, TCG_REG_30); +} + +static const uint8_t tcg_cond_to_jcc[10] = { +    [TCG_COND_EQ] = ARITH_CMPEQ, +    [TCG_COND_NE] = ARITH_CMPEQ, +    [TCG_COND_LT] = ARITH_CMPLT, +    [TCG_COND_GE] = ARITH_CMPLT, +    [TCG_COND_LE] = ARITH_CMPLE, +    [TCG_COND_GT] = ARITH_CMPLE, +    [TCG_COND_LTU] = ARITH_CMPULT, +    [TCG_COND_GEU] = ARITH_CMPULT, +    [TCG_COND_LEU] = ARITH_CMPULE, +    [TCG_COND_GTU] = ARITH_CMPULE +}; + +/* + * called by tcg_out_reloc() when the label address is determined,  + * i.e., label->has_value is true. what should be done is to patch  + * the jmp insn that reference this label. + * + * code_ptr - position need to patch + * type - relocation type + * value - label address + * addend - not used +*/ +static void patch_reloc(uint8_t *code_ptr, \ +    int type, tcg_target_long value, tcg_target_long addend) +{ +    TCGContext s; +      +    if ( type != R_ALPHA_REFQUAD) +        tcg_abort(); +      +    s.code_ptr = code_ptr; +    tcg_out_movi_fixl(&s, TCG_TYPE_I64, TMP_REG, value); +    tcg_out_inst3_func(&s, CONTROL_JMP, TCG_REG_31, TMP_REG, FUNC_JMP, 0); +} + +/* + * generate insns for BR or BRCOND  + * opc must be CONTROL_BR or CONTROL_BLBC or CONTROL_BLBS + * Ra fixed to TMP_REG +*/ +static void tcg_out_jxx(TCGContext *s, int opc, int Ra, int label_index) +{ +    tcg_target_long val; +    TCGLabel *l = &s->labels[label_index]; +     +    if ((Ra != TMP_REG) || +        (opc != CONTROL_BR && opc != CONTROL_BLBC && opc != CONTROL_BLBS) ) +        tcg_abort(); + +    if (l->has_value) { +        /* the label address has been resolved. */ +        val = (l->u.value - (tcg_target_long)s->code_ptr - 4) >> 2; +        if ( val >= -0x100000 && val < 0x100000) {         +            /* if distance can be put into 21-bit field */ +            tcg_out_inst2(s, opc, Ra, val); +        } else { +            /* distance can't be put into 21-bit field */ +            if ( opc != CONTROL_BR) { +                tcg_out_inst2(s, opc^4, Ra, 6);  +            } + +            tcg_out_movi_fixl(s, TCG_TYPE_I64, Ra, l->u.value); +            tcg_out_inst3_func(s, CONTROL_JMP, TCG_REG_31, Ra, FUNC_JMP, 0);    // jmp $31, TMP_REG, 0  +        } +    } else {  +        /*  +         * if the label addr has not been determined, we first insert a short jmp, +         * and then resv space (6 insns, 24 bytes) for long jmp  +        */ +        if ( opc != CONTROL_BR) { +            tcg_out_inst2(s, opc^4, Ra, 6);  +        } + +        /* record relocation infor */ +        tcg_out_reloc(s, s->code_ptr, R_ALPHA_REFQUAD, label_index, 0); +        s->code_ptr += 24; +    } +} + +/* + * generate insn for INDEX_op_brcond +*/ +static void tcg_out_brcond( TCGContext *s, int cond, \ +    TCGArg arg1, TCGArg arg2, int const_arg2, int label_index) +{ +    int Func, jcc_opc; + +    if ( cond < TCG_COND_EQ || cond > TCG_COND_GTU) +        tcg_abort(); + +    /* get function code according to condition */ +    Func = tcg_cond_to_jcc[cond]; +      +    if ( const_arg2) { +        tcg_out_movi(s, TCG_TYPE_I64, TMP_REG, arg2); +        tcg_out_inst4(s, ALPHA_ARITH, arg1, TMP_REG, Func, TMP_REG);    // CMPxx arg1, TMP_REG, TMP_REG +    } else { +        tcg_out_inst4(s, ALPHA_ARITH, arg1, arg2, Func, TMP_REG);        // CMPxx arg1, arg2, TMP_REG +    } + +    // +    // --------------------------------- +    //  cond & 1  |  TMP_REG  |  take? +    // --------------------------------- +    //      0     |     0     |   not +    //      0     |     1     |   yes +    //      1     |     0     |   yes +    //      1     |     1     |   not +    // --------------------------------- +    // +    jcc_opc = (cond & 1) ? CONTROL_BLBC : CONTROL_BLBS; +    tcg_out_jxx(s, jcc_opc, TMP_REG, label_index);      +} + + +#if defined(CONFIG_SOFTMMU) + +#include "../../softmmu_defs.h" + +static void *qemu_ld_helpers[4] = { +    __ldb_mmu, +    __ldw_mmu, +    __ldl_mmu, +    __ldq_mmu, +}; + +static void *qemu_st_helpers[4] = { +    __stb_mmu, +    __stw_mmu, +    __stl_mmu, +    __stq_mmu, +}; + +#endif + +/*  + * XXX: qemu_ld and qemu_st could be modified to clobber only EDX and + * EAX. It will be useful once fixed registers globals are less common.  + * + * output host insn for op 'qemu_ldxx t0, t1, flags', which means fetching value from t1 to t0. + * flags gives the current CPU mode, kernel or user. + * + * opc argument determines the data width and extension type (zero or signed), and has the  + * following layout: + *                            2  1  0 + * ------------------------------------ + * |                        | E |  W  | + * ------------------------------------ + * + * E = 0 means zero extention, 1 means signed extension + * W = 0 means byte, 1 means word, 2 means dword. + * + * Note that VM addr space may be 32-bit or 64-bit, below, we take 32-bit addr space as example + * when doing the comment. +*/ +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) +{ +    int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap; + +#if defined(CONFIG_SOFTMMU) +    uint8_t *label1_ptr, *label2_ptr; +#endif + +    data_reg = *args++; +    addr_reg = *args++; +    mem_index = *args; +    s_bits = opc & 3; + +    r0 = TCG_REG_16; +    r1 = TCG_REG_17; + +#if defined(CONFIG_SOFTMMU) + +    tcg_out_mov(s, r1, addr_reg);  +    tcg_out_mov(s, r0, addr_reg);  +  +#if TARGET_LONG_BITS == 32 +    /* if VM is of 32-bit arch, clear higher 32-bit of addr */ +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SLL, r0);                                // sll r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SRL, r0);                                // srl r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r1, 32, ARITH_SLL, r1);                                // sll r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r1, 32, ARITH_SRL, r1);                                // srl r0, 32, r0 +#endif + +    tgen_arithi(s, ALPHA_LOGIC, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));    // and r0, #b, r0  + +    // +    // after above insn, we got the page # stored in r0.  note that if VM addr space is 32 bits, +    // then the higher 32 bits of r0 should be 0 +    // +    //      32 31                         12 11                 1 0 +    // ------------------------------------------------------------- +    //  ...00 |             page#           |    ...0000...     |xx| +    // ------------------------------------------------------------- +    // + +    //  +    // the following 2 host insns are tricky. note that TLB has 256 entries, +    // and entry is (1<| +    // + +    tcg_out_addi(s, r1, offsetof(CPUState, tlb_table[mem_index][0].addr_read));            // addq r1, offset, r1 +    tcg_out_inst4(s, ALPHA_ARITH, r1, TCG_REG_15, ARITH_ADDQ, r1);                        // addq r1, $15, r1 +#if TARGET_LONG_BITS == 32 +    tcg_out_inst3_disp(s, ALPHA_LDL, TMP_REG, r1, 0);                                    // ldl TMP_REG, 0(r1) +    tcg_out_inst4i(s, ALPHA_SHIFT, TMP_REG, 32, ARITH_SLL, TMP_REG);                    // sll TMP_REG, 32, TMP_REG +    tcg_out_inst4i(s, ALPHA_SHIFT, TMP_REG, 32, ARITH_SRL, TMP_REG);                    // srl TMP_REG, 32, TMP_REG +#else +    tcg_out_inst3_disp(s, ALPHA_LDQ, TMP_REG, r1, 0);                                    // ldq TMP_REG, 0(r1) +#endif +          +    // +    // now, r0 contains the page# and TMP_REG contains the addr to tlb_entry.addr_read +    // we below will compare them +    // +    tcg_out_inst4(s, ALPHA_ARITH, TMP_REG, r0, ARITH_CMPEQ, TMP_REG);                    // cmpeq TMP_REG, r0, TMP_REG + +    tcg_out_mov(s, r0, addr_reg);  +#if TARGET_LONG_BITS == 32 +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SLL, r0);                                // sll r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SRL, r0);                                // srl r0, 32, r0 +#endif + +    // +    // if equal, we jump to label1. since label1 is not resolved yet,  +    // we just record a relocation. +    // +    label1_ptr = s->code_ptr; +    s->code_ptr += 4; + +    // +    // here, unequal, TLB-miss. +    // +    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_17, mem_index);                            // pass argument 2 +    tcg_out_movi(s, TCG_TYPE_I64, \ +        TMP_REG, (tcg_target_long)qemu_ld_helpers[s_bits]);                                // get helper func entry +    tcg_out_push(s, TCG_REG_26); +tcg_out_mov(s, TCG_REG_27, TMP_REG); +    tcg_out_inst3_func(s, CONTROL_CALL, TCG_REG_26, TMP_REG, FUNC_CALL, 0);                // call helper func +    tcg_out_pop(s, TCG_REG_26); +      +    // +    // after helper function call, the result of ld is saved in $0 +    // +    switch(opc) { +    case 0 | 4: +        tcg_out_inst4(s, ALPHA_SEXT, TCG_REG_31, TCG_REG_0, ARITH_SEXTB, data_reg);        // sextb $31, $0, data_reg +        break; +    case 1 | 4: +        tcg_out_inst4(s, ALPHA_SEXT, TCG_REG_31, TCG_REG_0, ARITH_SEXTW, data_reg);        // sextw $31, $0, data_reg +        break; +    case 2 | 4: +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 32, ARITH_SLL, TCG_REG_0);            // sll $0, 32, $0 +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 32, ARITH_SRA, data_reg);                // sra $0, 32, data_reg +        break; +    case 0: +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 56, ARITH_SLL, TCG_REG_0);            // sll $0, 56, $0 +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 56, ARITH_SRL, data_reg);                // srl $0, 56, data_reg +        break; +    case 1: +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 48, ARITH_SLL, TCG_REG_0);            // sll $0, 48, $0 +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 48, ARITH_SRL, data_reg);                // srl $0, 48, data_reg +        break; +    case 2: +    default: +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 32, ARITH_SLL, TCG_REG_0);            // sll $0, 32, $0 +        tcg_out_inst4i(s, ALPHA_SHIFT, TCG_REG_0, 32, ARITH_SRL, data_reg);                // srl $0, 32, data_reg +        break; +    case 3: +        tcg_out_mov(s, data_reg, TCG_REG_0); +        break; +    } + +    // +    // we have done, jmp to label2. label2 is not resolved yet,  +    // we record a relocation. +    // +    label2_ptr = s->code_ptr; +    s->code_ptr += 4; +     +    // patch jmp to label1 +    *(uint32_t *)label1_ptr = (uint32_t) \ +        ( ( CONTROL_BNE << 26 ) | ( TMP_REG << 21 ) \ +        | ( ((s->code_ptr-label1_ptr-4)>>2) & 0x1fffff) );                                // beq TMP_REG, disp  + +    // +    // if we get here, a TLB entry is hit, r0 contains the guest addr and  +    // r1 contains the ptr that point to tlb_entry.addr_read. what we should +    // do is to load the tlb_entry.addend (64-bit on alpha) and add it to  +    // r0 to get the host VA +    // +    tcg_out_movi(s, TCG_TYPE_I64, TMP_REG, \ +        offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read));                // TMP_REG <- distance btw addent and addr_read +    tcg_out_inst4(s, ALPHA_ARITH, r1, TMP_REG, ARITH_ADDQ, r1);                            // addq r1, TMP_REG, r1 +    tcg_out_inst3_disp(s, ALPHA_LDQ, TMP_REG, r1,  0);                                    // ldq TMP_REG, r1, 0 +    tcg_out_inst4(s, ALPHA_ARITH, r0, TMP_REG, ARITH_ADDQ, r0);                            // addq r0, TMP_REG, r0 +      +#else +    r0 = addr_reg; +#endif // endif defined(CONFIG_SOFTMMU) + + +#ifdef TARGET_WORDS_BIGENDIAN +    bswap = 1; +#else +    bswap = 0; +#endif + +    if ( bswap) { +        tcg_abort(); +    } + +    // +    // when we get here, r0 contains the host VA that can be used to access guest PA +    // +    switch(opc) { +    case 0: +        tcg_out_inst3_disp(s, ALPHA_LDBU, data_reg, r0, 0);                                // ldbu data_reg, 0(r0) +        break; +    case 0 | 4: +        tcg_out_inst3_disp(s, ALPHA_LDBU, data_reg, r0, 0);                                // ldbu data_reg, 0(r0) +        tcg_out_inst4(s, ALPHA_SEXT, TCG_REG_31, data_reg, ARITH_SEXTB, data_reg);        // sextb $31, data_reg, data_reg +        break; +    case 1: +        tcg_out_inst3_disp(s, ALPHA_LDWU, data_reg, r0, 0);                                // ldwu data_reg, 0(r0) +        break; +    case 1 | 4: +        tcg_out_inst3_disp(s, ALPHA_LDWU, data_reg, r0, 0);                                // ldwu data_reg, 0(r0) +        tcg_out_inst4(s, ALPHA_SEXT, TCG_REG_31, data_reg, ARITH_SEXTW, data_reg);        // sextw $31, data_reg, data_reg +        break; +    case 2: +        tcg_out_inst3_disp(s, ALPHA_LDL, data_reg, r0, 0);                                // ldl data_reg, 0(r0) +        tcg_out_inst4i(s, ALPHA_SHIFT, data_reg, 32, ARITH_SLL, data_reg);                // sll data_reg, 32, data_reg +        tcg_out_inst4i(s, ALPHA_SHIFT, data_reg, 32, ARITH_SRL, data_reg);                // srl data_reg, 32, data_reg +        break; +    case 2 | 4: +        tcg_out_inst3_disp(s, ALPHA_LDL, data_reg, r0, 0);                                // ldl data_reg, 0(r0) +        break; +    case 3: +        tcg_out_inst3_disp(s, ALPHA_LDQ, data_reg, r0, 0);                                // ldq data_reg, 0(r0) +        break; +    default: +        tcg_abort(); +    } + +#if defined(CONFIG_SOFTMMU) +    /* label2: */ +    *(uint32_t *)label2_ptr = (uint32_t)( ( CONTROL_BR << 26 ) \ +               | ( TCG_REG_31  << 21 ) |  +               ( ((s->code_ptr-label2_ptr-4)>>2) & 0x1fffff) ); +#endif +} + +static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) +{ +    int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap; +#if defined(CONFIG_SOFTMMU) +    uint8_t *label1_ptr, *label2_ptr; +#endif + +    data_reg = *args++; +    addr_reg = *args++; +    mem_index = *args; +    s_bits = opc&3; + +    r0 = TCG_REG_16; +    r1 = TCG_REG_17; + +#if defined(CONFIG_SOFTMMU) + +    tcg_out_mov(s, r1, addr_reg);  +    tcg_out_mov(s, r0, addr_reg);  +  +#if TARGET_LONG_BITS == 32 +    /* if VM is of 32-bit arch, clear higher 32-bit of addr */ +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SLL, r0);                                // sll r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SRL, r0);                                // srl r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r1, 32, ARITH_SLL, r1);                                // sll r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r1, 32, ARITH_SRL, r1);                                // srl r0, 32, r0 +#endif + +    tgen_arithi(s, ALPHA_LOGIC, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));    // and r0, #b, r0 + +    tgen_arithi(s, ALPHA_SHIFT, ARITH_SRL, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);    // srl r1, #b, r1     +    tgen_arithi(s, ALPHA_LOGIC, ARITH_AND, r1, (CPU_TLB_SIZE-1) << CPU_TLB_ENTRY_BITS);    // and r1, #b, r1 + +    tcg_out_addi(s, r1, offsetof(CPUState, tlb_table[mem_index][0].addr_write));        // addq r1, offset, r1 +    tcg_out_inst4(s, ALPHA_ARITH, r1, TCG_REG_15, ARITH_ADDQ, r1);                        // addq r1, $15, r1 + +#if TARGET_LONG_BITS == 32 +    tcg_out_inst3_disp(s, ALPHA_LDL, TMP_REG, r1, 0);                                    // ldl TMP_REG, 0(r1) +    tcg_out_inst4i(s, ALPHA_SHIFT, TMP_REG, 32, ARITH_SLL, TMP_REG);                    // sll TMP_REG, 32, TMP_REG +    tcg_out_inst4i(s, ALPHA_SHIFT, TMP_REG, 32, ARITH_SRL, TMP_REG);                    // srl TMP_REG, 32, TMP_REG +#else +    tcg_out_inst3_disp(s, ALPHA_LDQ, TMP_REG, r1, 0);                                    // ldq TMP_REG, 0(r1) +#endif + +    // +    // now, r0 contains the page# and TMP_REG contains the addr to tlb_entry.addr_read +    // we below will compare them +    //     +    tcg_out_inst4(s, ALPHA_ARITH, TMP_REG, r0, ARITH_CMPEQ, TMP_REG);                    // cmpeq TMP_REG, r0, TMP_REG + +    tcg_out_mov(s, r0, addr_reg);  +#if TARGET_LONG_BITS == 32 +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SLL, r0);                                // sll r0, 32, r0 +    tcg_out_inst4i(s, ALPHA_SHIFT, r0, 32, ARITH_SRL, r0);                                // srl r0, 32, r0 +#endif + +    // +    // if equal, we jump to label1. since label1 is not resolved yet,  +    // we just record a relocation. +    // +    label1_ptr = s->code_ptr; +    s->code_ptr += 4; + +    // here, unequal, TLB-miss, ... +    tcg_out_mov(s, TCG_REG_17, data_reg);                                                // pass argument 2 +    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_18, mem_index);                            // pass argument 3 +    tcg_out_movi(s, TCG_TYPE_I64, \ +        TMP_REG, (tcg_target_long)qemu_st_helpers[s_bits]);                                // get helper func entry +    tcg_out_push(s, TCG_REG_26); +tcg_out_mov(s, TCG_REG_27,TMP_REG); +    tcg_out_inst3_func(s, CONTROL_CALL, TCG_REG_26, TMP_REG, FUNC_CALL, 0);                // call helper func +    tcg_out_pop(s, TCG_REG_26); + +    // +    // we have done, jmp to label2. label2 is not resolved yet,  +    // we record a relocation. +    // +    label2_ptr = s->code_ptr; +    s->code_ptr += 4; +     +    // patch jmp to label1 +    *(uint32_t *)label1_ptr = (uint32_t) \ +        ( ( CONTROL_BNE << 26) | ( TMP_REG  << 21 ) +        | ( ((s->code_ptr-label1_ptr-4)>>2) & 0x1fffff) );                                // bne TMP_REG, disp  + +    // +    // if we get here, a TLB entry is hit, r0 contains the guest addr and  +    // r1 contains the ptr that point to tlb_entry.addr_read. what we should +    // do is to load the tlb_entry.addend (64-bit on alpha) and add it to  +    // r0 to get the host VA +    // +    tcg_out_movi(s, TCG_TYPE_I64, TMP_REG, \ +        offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write));                // TMP_REG <- distance btw addent and addr_write +    tcg_out_inst4(s, ALPHA_ARITH, r1, TMP_REG, ARITH_ADDQ, r1);                            // addq r1, TMP_REG, r1 +    tcg_out_inst3_disp(s, ALPHA_LDQ, TMP_REG, r1,  0);                                    // ldq TMP_REG, r1, 0 +    tcg_out_inst4(s, ALPHA_ARITH, r0, TMP_REG, ARITH_ADDQ, r0);                            // addq r0, TMP_REG, r0 + +#else +    r0 = addr_reg; +#endif + +#ifdef TARGET_WORDS_BIGENDIAN +    bswap = 1; +#else +    bswap = 0; +#endif + +    if ( bswap) { +        tcg_abort(); +    } + +    // +    // when we get here, r0 contains the host VA that can be used to access guest PA +    // +    switch(opc) { +    case 0: +        tcg_out_inst3_disp(s, ALPHA_STB, data_reg, r0, 0);                                // stb data_reg, 0(r0) +        break; +    case 1: +        tcg_out_inst3_disp(s, ALPHA_STW, data_reg, r0, 0);                                // stw data_reg, 0(r0) +        break; +    case 2: +        tcg_out_inst3_disp(s, ALPHA_STL, data_reg, r0, 0);                                // stl data_reg, 0(r0) +        break; +    case 3: +        tcg_out_inst3_disp(s, ALPHA_STQ, data_reg, r0, 0);                                // stq data_reg, 0(r0) +        break; +    default: +        tcg_abort(); +    } + +#if defined(CONFIG_SOFTMMU) +    /* label2: */ +    *(uint32_t *)label2_ptr = (uint32_t)( ( CONTROL_BR << 26 ) \ +        | ( TCG_REG_31  << 21 ) | ( ((s->code_ptr-label2_ptr-4)>>2) & 0x1fffff)); +#endif +} + +static inline void tgen_ldxx( TCGContext *s, int Ra, int Rb, tcg_target_long disp, int flags) +{ +    int opc_array[4] = { ALPHA_LDBU, ALPHA_LDWU, ALPHA_LDL, ALPHA_LDQ}; +    int opc = opc_array[flags & 3]; + +    if( disp != (int16_t)disp ) { +        /* disp cannot be stored in insn directly */ +        tcg_out_movi(s, TCG_TYPE_I64, TMP_REG, disp);      +        tcg_out_inst4(s, ALPHA_ARITH, Rb, TMP_REG, ARITH_ADDQ, TMP_REG);                    // addq r, TMP_REG, TMP_REG +        tcg_out_inst3_disp(s, opc, Ra, TMP_REG, 0);                                    // ldx ret, 0(TMP_REG) +    } else { +        tcg_out_inst3_disp(s, opc, Ra, Rb, disp);                                        // ldx ret, disp(r) +    } + +    switch ( flags & 7)    { +    case 0: +    case 1: +    case 2|4: +    case 3: +        break; +    case 0|4: +        tcg_out_inst4(s, ALPHA_SEXT, TCG_REG_31, Ra, ARITH_SEXTB, Ra);                // sextb $31, ra, ra +        break; +    case 1|4: +        tcg_out_inst4(s, ALPHA_SEXT, TCG_REG_31, Ra, ARITH_SEXTW, Ra);                // sextw $31, ra, ra +        break; +    case 2: +        tcg_out_inst4i(s, ALPHA_SHIFT, Ra, 32, ARITH_SLL, Ra);                        // sll ret, 32, ret +        tcg_out_inst4i(s, ALPHA_SHIFT, Ra, 32, ARITH_SRL, Ra);                        // srl ret, 32, ret +        break; +    default: +        tcg_abort(); +    } +} + +static inline void tgen_stxx( TCGContext *s, int Ra, int Rb, tcg_target_long disp, int flags) +{ +    int opc_array[4] = { ALPHA_STB, ALPHA_STW, ALPHA_STL, ALPHA_STQ}; +    int opc = opc_array[flags & 3]; + +    if( disp != (int16_t)disp ) { +        /* disp cannot be stored in insn directly */ +        tcg_out_movi(s, TCG_TYPE_I64, TMP_REG, disp); +        tcg_out_inst4(s, ALPHA_ARITH, Rb, TMP_REG, ARITH_ADDQ, TMP_REG);            // addq Rb, TMP_REG, TMP_REG +        tcg_out_inst3_disp(s, opc, Ra, TMP_REG, 0);                                // stx Ra, 0(TMP_REG) +    } else { +        tcg_out_inst3_disp(s, opc, Ra, Rb, disp);                                // stx Ra, disp(Rb) +    } +} + +static inline void tcg_out_op(TCGContext *s, \ +    int opc, const TCGArg *args, const int *const_args) +{ +    int oc, c; +    switch(opc)  +    { +    case INDEX_op_exit_tb: +        /* +         * exit_tb t0, where t0 is always constant and should be returned to engine  +         * since we'll back to engine soon, $0 and $1 will never be used +        */ +        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_0, args[0]); +        tcg_out_movi(s, TCG_TYPE_I64, TMP_REG, (tcg_target_long)tb_ret_addr); +        tcg_out_inst3_func(s, CONTROL_JMP, TCG_REG_31, TMP_REG, FUNC_JMP, 0);            // jmp $31, TMP_REG, hint +        break; + +    case INDEX_op_goto_tb: +        /* goto_tb idx, where idx is constant 0 or 1, indicating the branch # */ +        if (s->tb_jmp_offset) { +            /* we don't support direct jmp */ +            tcg_abort(); +        } else { +            /* indirect jump method */ +        tcg_out_movi( s, TCG_TYPE_I64, TMP_REG, (tcg_target_long)(s->tb_next + args[0])); +        tcg_out_ld( s, TCG_TYPE_I64, TMP_REG, TMP_REG, 0); +        tcg_out_inst3_func(s, CONTROL_JMP, TCG_REG_31, TMP_REG, FUNC_JMP, 0);        // jmp $31, TMP_REG, hint +        } +        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; +        break; + +    case INDEX_op_call: +        /* call ptr, where ptr has be stored in args[0] */ +        if (const_args[0]) { +            tcg_abort(); +        } else { +            tcg_out_push( s, TCG_REG_26); +            tcg_out_mov( s, TCG_REG_27, args[0]); +            tcg_out_inst3_func(s, CONTROL_CALL, TCG_REG_26, args[0], FUNC_CALL, 0); +            tcg_out_pop( s, TCG_REG_26); +        } +        break; + +    case INDEX_op_jmp:  +        /* jmp t0, where t0 gives the target address */ +        if (const_args[0]) { +            tcg_abort(); +        } else { +            tcg_out_inst3_func(s, CONTROL_JMP, TCG_REG_31, args[0], FUNC_JMP, 0); +        } +        break; + +    case INDEX_op_br:  +        /* br idx, where idx gives the label index */ +        tcg_out_jxx(s, CONTROL_BR, TMP_REG, args[0]); +        break; + +    case INDEX_op_mov_i32:  +    case INDEX_op_mov_i64: +        /* mov_i32/i64 t0, t1, implemented in tcg.c:tcg_reg_alloc_mov() */ +        tcg_abort(); +        break; + +    case INDEX_op_movi_i32:  +    case INDEX_op_movi_i64:  +        /* movi_i32/i64 t0, t1, implemented in tcg.c:tcg_reg_alloc_movi() */ +        tcg_abort(); +        break; +          +    case INDEX_op_ld8u_i32:  +    case INDEX_op_ld8u_i64: +        /* ld8u_i32/i64 t0, t1, offset */ +        tgen_ldxx( s, args[0], args[1], args[2], 0); +        break; + +    case INDEX_op_ld8s_i32:  +    case INDEX_op_ld8s_i64:  +        /* ld8s_i32/i64 t0, t1, offset */ +        tgen_ldxx( s, args[0], args[1], args[2], 0|4); +        break; + +    case INDEX_op_ld16u_i32: +    case INDEX_op_ld16u_i64: +        /* ld16u_i32/i64 t0, t1, offset */ +          tgen_ldxx( s, args[0], args[1], args[2], 1); +        break; + +    case INDEX_op_ld16s_i32: +    case INDEX_op_ld16s_i64:  +        /* ld16s_i32/i64 t0, t1, offset */ +        tgen_ldxx( s, args[0], args[1], args[2], 1|4); +        break; + +    case INDEX_op_ld32u_i64:  +        /* ld32u_i64 t0, t1, offset */ +        tgen_ldxx( s, args[0], args[1], args[2], 2); +        break; + +    case INDEX_op_ld_i32:  +    case INDEX_op_ld32s_i64: +        /* ld_i32 t0, t1, offset or ld32s_i64 t0, t1, offset */ +        tgen_ldxx( s, args[0], args[1], args[2], 2|4); +        break; + +    case INDEX_op_ld_i64:  +        /* ld_i32 t0, t1, offset */ +        tgen_ldxx( s, args[0], args[1], args[2], 3); +        break; +          +    case INDEX_op_st8_i32: +    case INDEX_op_st8_i64:  +        /* st8_i32/i64 t0, t1, offset */ +        tgen_stxx( s, args[0], args[1], args[2], 0); +        break; + +    case INDEX_op_st16_i32: +    case INDEX_op_st16_i64:  +        /* st16_i32/i64 t0, t1, offset */ +        tgen_stxx( s, args[0], args[1], args[2], 1); +        break; + +    case INDEX_op_st_i32: +    case INDEX_op_st32_i64:  +        /* st_i32/st32_i64 t0, t1, offset */ +        tgen_stxx( s, args[0], args[1], args[2], 2); +        break; + +    case INDEX_op_st_i64:  +        /* st_i64 t0, t1, offset */ +        tgen_stxx( s, args[0], args[1], args[2], 3); +        break; + +    case INDEX_op_add_i32:  +        /* add_i32 t0, t1, t2 */ +        oc = ALPHA_ARITH; +        c = ARITH_ADDL; +        goto gen_arith; +    case INDEX_op_add_i64:  +        /* add_i64 t0, t1, t2 */ +        oc = ALPHA_ARITH; +        c = ARITH_ADDQ; +        goto gen_arith; +    case INDEX_op_sub_i32:  +        /* sub_i32 t0, t1, t2 */ +        oc = ALPHA_ARITH; +        c = ARITH_SUBL; +        goto gen_arith; +    case INDEX_op_sub_i64:  +        /* sub_i84 t0, t1, t2 */ +        oc = ALPHA_ARITH; +        c = ARITH_SUBQ; +        goto gen_arith; +    case INDEX_op_mul_i32:  +        /* mul_i32 t0, t1, t2 */ +        oc = ALPHA_MUL; +        c = ARITH_MULL; +        goto gen_arith; +    case INDEX_op_mul_i64:  +        /* mul_i64 t0, t1, t2 */ +        oc = ALPHA_MUL; +        c = ARITH_MULQ; +        goto gen_arith; +    case INDEX_op_and_i32: +    case INDEX_op_and_i64: +        /* and_i32/i64 t0, t1, t2 */ +        oc = ALPHA_LOGIC; +        c = ARITH_AND; +        goto gen_arith; +    case INDEX_op_or_i32: +    case INDEX_op_or_i64:  +        /* or_i32/i64 t0, t1, t2 */ +        oc = ALPHA_LOGIC; +        c = ARITH_BIS; +        goto gen_arith; +    case INDEX_op_xor_i32: +    case INDEX_op_xor_i64: +        /* xor_i32/i64 t0, t1, t2 */ +        oc = ALPHA_LOGIC; +        c = ARITH_XOR; +        goto gen_arith; +    case INDEX_op_shl_i32: +    case INDEX_op_shl_i64: +        /* shl_i32/i64 t0, t1, t2 */ +        oc = ALPHA_SHIFT; +        c = ARITH_SLL; +        goto gen_arith; +    case INDEX_op_shr_i32: +        tcg_out_inst4i(s, ALPHA_SHIFT, args[0], 32, ARITH_SLL, args[0]); +        tcg_out_inst4i(s, ALPHA_SHIFT, args[0], 32, ARITH_SRL, args[0]); +    case INDEX_op_shr_i64:  +        /* shr_i32/i64 t0, t1, t2 */ +        oc = ALPHA_SHIFT; +        c = ARITH_SRL; +        goto gen_arith; +    case INDEX_op_sar_i32:     +        tcg_out_inst4i(s, ALPHA_SHIFT, args[0], 32, ARITH_SLL, args[0]); +        tcg_out_inst4i(s, ALPHA_SHIFT, args[0], 32, ARITH_SRA, args[0]); +    case INDEX_op_sar_i64: +        /* sar_i32/i64 t0, t1, t2 */ +        oc = ALPHA_SHIFT; +        c = ARITH_SRA; +    gen_arith: +        if (const_args[2]) { +            tgen_arithi(s, oc, c, args[0], args[2]); +        } else { +            tcg_out_inst4(s, oc, args[0], args[2], c, args[0]); +        } +        break; + +    case INDEX_op_brcond_i32: +    case INDEX_op_brcond_i64: +        /* brcond_i32/i64 t0, t1, cond, label */ +        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]); +        break; + +    case INDEX_op_qemu_ld8u: +        tcg_out_qemu_ld(s, args, 0); +        break; +    case INDEX_op_qemu_ld8s: +        tcg_out_qemu_ld(s, args, 0 | 4); +        break; +    case INDEX_op_qemu_ld16u: +        tcg_out_qemu_ld(s, args, 1); +        break; +    case INDEX_op_qemu_ld16s: +        tcg_out_qemu_ld(s, args, 1 | 4); +        break; +    case INDEX_op_qemu_ld32u: +        tcg_out_qemu_ld(s, args, 2); +        break; +    case INDEX_op_qemu_ld32s: +        tcg_out_qemu_ld(s, args, 2 | 4); +        break; +    case INDEX_op_qemu_ld64: +        tcg_out_qemu_ld(s, args, 3); +        break; + +    case INDEX_op_qemu_st8: +        tcg_out_qemu_st(s, args, 0); +        break; +    case INDEX_op_qemu_st16: +        tcg_out_qemu_st(s, args, 1); +        break; +    case INDEX_op_qemu_st32: +        tcg_out_qemu_st(s, args, 2); +        break; +    case INDEX_op_qemu_st64: +        tcg_out_qemu_st(s, args, 3); +        break; + +    case INDEX_op_div2_i32: +    case INDEX_op_divu2_i32: +    default: +        tcg_abort(); +    } + +            tcg_out_inst4(s, ALPHA_LOGIC, 31, 31, ARITH_AND, 31); +} + +static const TCGTargetOpDef alpha_op_defs[] = { +    { INDEX_op_exit_tb, { } }, +    { INDEX_op_goto_tb, { } }, +    { INDEX_op_call, { "r" } }, +    { INDEX_op_jmp, { "r" } }, +    { INDEX_op_br, { } }, + +    { INDEX_op_mov_i32, { "r", "r" } }, +    { INDEX_op_movi_i32, { "r" } }, +    { INDEX_op_ld8u_i32, { "r", "r" } }, +    { INDEX_op_ld8s_i32, { "r", "r" } }, +    { INDEX_op_ld16u_i32, { "r", "r" } }, +    { INDEX_op_ld16s_i32, { "r", "r" } }, +    { INDEX_op_ld_i32, { "r", "r" } }, +    { INDEX_op_st8_i32, { "r", "r" } }, +    { INDEX_op_st16_i32, { "r", "r" } }, +    { INDEX_op_st_i32, { "r", "r" } }, + +    { INDEX_op_add_i32, { "r", "0", "ri" } }, +    { INDEX_op_mul_i32, { "r", "0", "ri" } }, +    //{ INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } }, +    //{ INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } }, +    { INDEX_op_sub_i32, { "r", "0", "ri" } }, +    { INDEX_op_and_i32, { "r", "0", "ri" } }, +    { INDEX_op_or_i32, { "r", "0", "ri" } }, +    { INDEX_op_xor_i32, { "r", "0", "ri" } }, + +    { INDEX_op_shl_i32, { "r", "0", "ri" } }, +    { INDEX_op_shr_i32, { "r", "0", "ri" } }, +    { INDEX_op_sar_i32, { "r", "0", "ri" } }, + +    { INDEX_op_brcond_i32, { "r", "ri" } },          + +    { INDEX_op_mov_i64, { "r", "r" } },      +    { INDEX_op_movi_i64, { "r" } }, +    { INDEX_op_ld8u_i64, { "r", "r" } }, +    { INDEX_op_ld8s_i64, { "r", "r" } }, +    { INDEX_op_ld16u_i64, { "r", "r" } }, +    { INDEX_op_ld16s_i64, { "r", "r" } }, +    { INDEX_op_ld32u_i64, { "r", "r" } }, +    { INDEX_op_ld32s_i64, { "r", "r" } }, +    { INDEX_op_ld_i64, { "r", "r" } }, +    { INDEX_op_st8_i64, { "r", "r" } },      +    { INDEX_op_st16_i64, { "r", "r" } }, +    { INDEX_op_st32_i64, { "r", "r" } }, +    { INDEX_op_st_i64, { "r", "r" } }, + +    { INDEX_op_add_i64, { "r", "0", "ri" } }, +    { INDEX_op_mul_i64, { "r", "0", "ri" } }, +    //{ INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } }, +    //{ INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } }, +    { INDEX_op_sub_i64, { "r", "0", "ri" } }, +    { INDEX_op_and_i64, { "r", "0", "ri" } }, +    { INDEX_op_or_i64, { "r", "0", "ri" } }, +    { INDEX_op_xor_i64, { "r", "0", "ri" } }, + +    { INDEX_op_shl_i64, { "r", "0", "ri" } }, +    { INDEX_op_shr_i64, { "r", "0", "ri" } }, +    { INDEX_op_sar_i64, { "r", "0", "ri" } }, + +    { INDEX_op_brcond_i64, { "r", "ri" } }, + +    { INDEX_op_qemu_ld8u, { "r", "L" } }, +    { INDEX_op_qemu_ld8s, { "r", "L" } }, +    { INDEX_op_qemu_ld16u, { "r", "L" } }, +    { INDEX_op_qemu_ld16s, { "r", "L" } }, +    { INDEX_op_qemu_ld32u, { "r", "L" } }, +    { INDEX_op_qemu_ld32s, { "r", "L" } }, +    { INDEX_op_qemu_ld64, { "r", "L" } }, + +    { INDEX_op_qemu_st8, { "L", "L" } }, +    { INDEX_op_qemu_st16, { "L", "L" } }, +    { INDEX_op_qemu_st32, { "L", "L" } }, +    { INDEX_op_qemu_st64, { "L", "L", "L" } }, + +    { -1 }, +}; + + +static int tcg_target_callee_save_regs[] = { +    /* TCG_REG_15, */                                // used for the global env, so no need to save +    TCG_REG_9, +    TCG_REG_10, +    TCG_REG_11, +    TCG_REG_12, +    TCG_REG_13, +    TCG_REG_14 +}; + +/* + * Generate global QEMU prologue and epilogue code  +*/ +void tcg_target_qemu_prologue(TCGContext *s) +{ +    int i, frame_size, push_size, stack_addend; +     +    /* TB prologue */ +/*printf("TB prologue @ %lx\n", s->code_ptr);*/ +      +    /* save TCG_REG_26 */ +    tcg_out_push(s, TCG_REG_26); + +    /* save all callee saved registers */ +    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { +        tcg_out_push(s, tcg_target_callee_save_regs[i]); +    } +      +    /* reserve some stack space */ +    push_size = 8 + (1 + ARRAY_SIZE(tcg_target_callee_save_regs)) * 8; +    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE; +    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & ~(TCG_TARGET_STACK_ALIGN - 1); +    stack_addend = frame_size - push_size; +    tcg_out_addi(s, TCG_REG_30, -stack_addend); + +    tcg_out_inst3_func(s, CONTROL_JMP, TCG_REG_31, TCG_REG_16, FUNC_JMP, 0);        /* jmp $16 */ + +    /* TB epilogue */ +    tb_ret_addr = s->code_ptr; +    tcg_out_addi(s, TCG_REG_30, stack_addend); +    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) { +        tcg_out_pop(s, tcg_target_callee_save_regs[i]); +    } + +    tcg_out_pop(s, TCG_REG_26); +    tcg_out_inst3_func(s, CONTROL_RET, TCG_REG_31, TCG_REG_26, FUNC_RET, 0);        /* ret */ +} + + +void tcg_target_init(TCGContext *s) +{ +    /* fail safe */ +    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) +        tcg_abort(); + +    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); +    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); +    tcg_regset_set32(tcg_target_call_clobber_regs, 0, +        (1 << TCG_REG_1  ) | (1 << TCG_REG_2 ) | (1 << TCG_REG_3  ) | (1 << TCG_REG_4 ) | +        (1 << TCG_REG_5  ) | (1 << TCG_REG_6 ) | (1 << TCG_REG_7  ) | (1 << TCG_REG_8 ) |  +        (1 << TCG_REG_22) | (1 << TCG_REG_23) | (1 << TCG_REG_24) | (1 << TCG_REG_25) |  +              (1 << TCG_REG_16) | (1 << TCG_REG_17) | (1 << TCG_REG_18) | (1 << TCG_REG_19) |  +              (1 << TCG_REG_20) | (1 << TCG_REG_21) | (1 << TCG_REG_0 )); +     +    tcg_regset_clear(s->reserved_regs); +    tcg_regset_set_reg(s->reserved_regs, TCG_REG_26); +    tcg_regset_set_reg(s->reserved_regs, TCG_REG_27); +    tcg_regset_set_reg(s->reserved_regs, TCG_REG_28); +    tcg_regset_set_reg(s->reserved_regs, TCG_REG_29); +    tcg_regset_set_reg(s->reserved_regs, TCG_REG_30); +    tcg_regset_set_reg(s->reserved_regs, TCG_REG_31);    // $15, $26~$31 not alloced by tcg.c +    tcg_regset_set_reg(s->reserved_regs, TMP_REG);        // reserved register for used in this file + +    tcg_add_target_add_op_defs(alpha_op_defs); +    printf("tcg_init called.\n"); +} + diff -urN qemu-0.10.0/tcg/alpha/tcg-target.h qemu-0.10.0.alpha/tcg/alpha/tcg-target.h --- qemu-0.10.0/tcg/alpha/tcg-target.h    1969-12-31 16:00:00.000000000 -0800 +++ qemu-0.10.0.alpha/tcg/alpha/tcg-target.h    2009-10-23 23:09:46.000000000 -0700 @@ -0,0 +1,60 @@ +/* + * 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. + */ +#define TCG_TARGET_ALPHA 1 + +#define TCG_TARGET_REG_BITS 64 + +#define TCG_TARGET_NB_REGS 32 + +enum { +    TCG_REG_0 = 0, TCG_REG_1, TCG_REG_2, TCG_REG_3, +     TCG_REG_4, TCG_REG_5, TCG_REG_6, TCG_REG_7, +    TCG_REG_8, TCG_REG_9, TCG_REG_10, TCG_REG_11, +    TCG_REG_12, TCG_REG_13, TCG_REG_14, TCG_REG_15, +    TCG_REG_16, TCG_REG_17, TCG_REG_18, TCG_REG_19, +    TCG_REG_20, TCG_REG_21, TCG_REG_22, TCG_REG_23, +    TCG_REG_24, TCG_REG_25, TCG_REG_26, TCG_REG_27, +    TCG_REG_28, TCG_REG_29, TCG_REG_30, TCG_REG_31 +}; + +/* used for function call generation */ +#define TCG_REG_CALL_STACK TCG_REG_30  +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_STACK_OFFSET 0 + +/* Note: must be synced with dyngen-exec.h */ +#define TCG_AREG0 TCG_REG_15 +#define TCG_AREG1 TCG_REG_9 +#define TCG_AREG2 TCG_REG_10 +#define TCG_AREG3 TCG_REG_11 +#define TCG_AREG4 TCG_REG_12 +#define TCG_AREG5 TCG_REG_13 +#define TCG_AREG6 TCG_REG_14 + +#define TMP_REG TCG_REG_25 + +static inline void flush_icache_range(unsigned long start, unsigned long stop) +{ +    asm("call_pal 0x86"); +}