Revision 3979144c tcg/arm/tcg-target.c

b/tcg/arm/tcg-target.c
90 90
    return 4;
91 91
}
92 92

  
93
#define USE_TLB
94

  
95 93
/* parse target specific constraints */
96 94
int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
97 95
{
......
115 113
    case 'x':
116 114
        ct->ct |= TCG_CT_REG;
117 115
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
118
# ifdef USE_TLB
119 116
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
120 117
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
121
# endif
122
        break;
123

  
124
    /* qemu_ld/st data_reg */
125
    case 'd':
126
        ct->ct |= TCG_CT_REG;
127
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
128
        /* r0 and optionally r1 will be overwritten by the address
129
         * so don't use these.  */
130
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
131
# if TARGET_LONG_BITS == 64 || defined(USE_TLB)
132
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
133
# endif
134 118
        break;
135 119

  
136 120
    /* qemu_ld/st64 data_reg2 */
......
153 137
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
154 138
        /* r0 will be overwritten by the low word of base, so don't use it.  */
155 139
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
156
#  ifdef USE_TLB
157 140
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
158
#  endif
159 141
        break;
160 142
# endif
161 143
#endif
......
210 192
    ARITH_ADC = 0x5,
211 193
    ARITH_SBC = 0x6,
212 194
    ARITH_RSC = 0x7,
195
    ARITH_TST = 0x8,
213 196
    ARITH_CMP = 0xa,
214 197
    ARITH_CMN = 0xb,
215 198
    ARITH_ORR = 0xc,
......
218 201
    ARITH_MVN = 0xf,
219 202
};
220 203

  
221
#define TO_CPSR(opc)		((opc == ARITH_CMP || opc == ARITH_CMN) << 20)
204
#define TO_CPSR(opc) \
205
  ((opc == ARITH_CMP || opc == ARITH_CMN || opc == ARITH_TST) << 20)
222 206

  
223 207
#define SHIFT_IMM_LSL(im)	(((im) << 7) | 0x00)
224 208
#define SHIFT_IMM_LSR(im)	(((im) << 7) | 0x20)
......
309 293
static inline void tcg_out_dat_imm(TCGContext *s,
310 294
                int cond, int opc, int rd, int rn, int im)
311 295
{
312
    tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) |
296
    tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) | TO_CPSR(opc) |
313 297
                    (rn << 16) | (rd << 12) | im);
314 298
}
315 299

  
......
428 412
                    (rn << 16) | (rd << 12) | rm);
429 413
}
430 414

  
415
/* Register pre-increment with base writeback.  */
416
static inline void tcg_out_ld32_rwb(TCGContext *s, int cond,
417
                int rd, int rn, int rm)
418
{
419
    tcg_out32(s, (cond << 28) | 0x07b00000 |
420
                    (rn << 16) | (rd << 12) | rm);
421
}
422

  
423
static inline void tcg_out_st32_rwb(TCGContext *s, int cond,
424
                int rd, int rn, int rm)
425
{
426
    tcg_out32(s, (cond << 28) | 0x07a00000 |
427
                    (rn << 16) | (rd << 12) | rm);
428
}
429

  
431 430
static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
432 431
                int rd, int rn, tcg_target_long im)
433 432
{
......
826 825
};
827 826
#endif
828 827

  
828
#define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
829

  
829 830
static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
830 831
                const TCGArg *args, int opc)
831 832
{
......
835 836
# if TARGET_LONG_BITS == 64
836 837
    int addr_reg2;
837 838
# endif
838
# ifdef USE_TLB
839 839
    uint32_t *label_ptr;
840
# endif
841 840
#endif
842 841

  
843 842
    data_reg = *args++;
......
853 852
    mem_index = *args;
854 853
    s_bits = opc & 3;
855 854

  
856
# ifdef USE_TLB
857 855
    /* Should generate something like the following:
858
     *  ror r8, addr_reg, #TARGET_PAGE_BITS
856
     *  shr r8, addr_reg, #TARGET_PAGE_BITS
859 857
     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
860
     *  add r0, T0, r0 lsl #CPU_TLB_ENTRY_BITS
858
     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
861 859
     */
862 860
#  if CPU_TLB_BITS > 8
863 861
#   error
864 862
#  endif
865 863
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
866
                    8, 0, addr_reg, SHIFT_IMM_ROR(TARGET_PAGE_BITS));
864
                    8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
867 865
    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
868 866
                    0, 8, CPU_TLB_SIZE - 1);
869 867
    tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
......
875 873
     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
876 874
     * before.
877 875
     */
878
#  define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
879 876
    if (mem_index)
880 877
        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
881 878
                        (mem_index << (TLB_SHIFT & 1)) |
......
884 881
                    offsetof(CPUState, tlb_table[0][0].addr_read));
885 882
    tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
886 883
                    0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
887
    /* TODO: alignment check?
888
     * if (s_bits)
889
     * tcg_out_data_reg(s, COND_EQ, ARITH_EOR,
890
     *                  0, 1, 8, SHIFT_IMM_LSR(32 - s_bits));
891
     */
884
    /* Check alignment.  */
885
    if (s_bits)
886
        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
887
                        0, addr_reg, (1 << s_bits) - 1);
892 888
#  if TARGET_LONG_BITS == 64
893 889
    /* XXX: possibly we could use a block data load or writeback in
894 890
     * the first access.  */
......
918 914
        tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, 1);
919 915
        break;
920 916
    case 3:
921
        /* TODO: must write back */
922
        tcg_out_ld32_r(s, COND_EQ, data_reg, 1, addr_reg);
917
        tcg_out_ld32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
923 918
        tcg_out_ld32_12(s, COND_EQ, data_reg2, 1, 4);
924 919
        break;
925 920
    }
926 921

  
927 922
    label_ptr = (void *) s->code_ptr;
928 923
    tcg_out_b(s, COND_EQ, 8);
929
# endif
930 924

  
931 925
# ifdef SAVE_LR
932 926
    tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
......
969 963
                            data_reg, 0, 0, SHIFT_IMM_LSL(0));
970 964
        break;
971 965
    case 3:
966
        tcg_out_dat_reg(s, cond, ARITH_MOV,
967
                        data_reg, 0, 0, SHIFT_IMM_LSL(0));
972 968
        if (data_reg2 != 1)
973 969
            tcg_out_dat_reg(s, cond, ARITH_MOV,
974 970
                            data_reg2, 0, 1, SHIFT_IMM_LSL(0));
975
        if (data_reg != 0)
976
            tcg_out_dat_reg(s, cond, ARITH_MOV,
977
                            data_reg, 0, 0, SHIFT_IMM_LSL(0));
978 971
        break;
979 972
    }
980 973

  
......
982 975
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
983 976
# endif
984 977

  
985
# ifdef USE_TLB
986 978
    *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
987
# endif
988 979
#else
989 980
    switch (opc) {
990 981
    case 0:
......
1021 1012
# if TARGET_LONG_BITS == 64
1022 1013
    int addr_reg2;
1023 1014
# endif
1024
# ifdef USE_TLB
1025 1015
    uint32_t *label_ptr;
1026
# endif
1027 1016
#endif
1028 1017

  
1029 1018
    data_reg = *args++;
......
1039 1028
    mem_index = *args;
1040 1029
    s_bits = opc & 3;
1041 1030

  
1042
# ifdef USE_TLB
1043 1031
    /* Should generate something like the following:
1044
     *  ror r8, addr_reg, #TARGET_PAGE_BITS
1032
     *  shr r8, addr_reg, #TARGET_PAGE_BITS
1045 1033
     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
1046
     *  add r0, T0, r0 lsl #CPU_TLB_ENTRY_BITS
1034
     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1047 1035
     */
1048 1036
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1049
                    8, 0, addr_reg, SHIFT_IMM_ROR(TARGET_PAGE_BITS));
1037
                    8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1050 1038
    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1051 1039
                    0, 8, CPU_TLB_SIZE - 1);
1052 1040
    tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
......
1066 1054
                    offsetof(CPUState, tlb_table[0][0].addr_write));
1067 1055
    tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
1068 1056
                    0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1069
    /* TODO: alignment check?
1070
     * if (s_bits)
1071
     * tcg_out_data_reg(s, COND_EQ, ARITH_EOR,
1072
     *                  0, 1, 8, SHIFT_IMM_LSR(32 - s_bits));
1073
     */
1057
    /* Check alignment.  */
1058
    if (s_bits)
1059
        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1060
                        0, addr_reg, (1 << s_bits) - 1);
1074 1061
#  if TARGET_LONG_BITS == 64
1075 1062
    /* XXX: possibly we could use a block data load or writeback in
1076 1063
     * the first access.  */
......
1101 1088
        tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, 1);
1102 1089
        break;
1103 1090
    case 3:
1104
        /* TODO: must write back */
1105
        tcg_out_st32_r(s, COND_EQ, data_reg, 1, addr_reg);
1091
        tcg_out_st32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
1106 1092
        tcg_out_st32_12(s, COND_EQ, data_reg2, 1, 4);
1107 1093
        break;
1108 1094
    }
1109 1095

  
1110 1096
    label_ptr = (void *) s->code_ptr;
1111 1097
    tcg_out_b(s, COND_EQ, 8);
1112
# endif
1113 1098

  
1114 1099
    /* TODO: move this code to where the constants pool will be */
1115 1100
    if (addr_reg)
......
1195 1180
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
1196 1181
# endif
1197 1182

  
1198
# ifdef USE_TLB
1199 1183
    *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
1200
# endif
1201 1184
#else
1202 1185
    switch (opc) {
1203 1186
    case 0:
......
1512 1495
    { INDEX_op_qemu_ld16u, { "r", "x", "X" } },
1513 1496
    { INDEX_op_qemu_ld16s, { "r", "x", "X" } },
1514 1497
    { INDEX_op_qemu_ld32u, { "r", "x", "X" } },
1515
    { INDEX_op_qemu_ld64, { "r", "d", "x", "X" } },
1498
    { INDEX_op_qemu_ld64, { "x", "r", "x", "X" } },
1516 1499

  
1517
    { INDEX_op_qemu_st8, { "d", "x", "X" } },
1518
    { INDEX_op_qemu_st16, { "d", "x", "X" } },
1519
    { INDEX_op_qemu_st32, { "d", "x", "X" } },
1520
    { INDEX_op_qemu_st64, { "d", "D", "x", "X" } },
1500
    { INDEX_op_qemu_st8, { "x", "x", "X" } },
1501
    { INDEX_op_qemu_st16, { "x", "x", "X" } },
1502
    { INDEX_op_qemu_st32, { "x", "x", "X" } },
1503
    { INDEX_op_qemu_st64, { "x", "D", "x", "X" } },
1521 1504

  
1522 1505
    { INDEX_op_ext8s_i32, { "r", "r" } },
1523 1506
    { INDEX_op_ext16s_i32, { "r", "r" } },

Also available in: Unified diff