Revision b03cce8e

b/tcg/i386/tcg-target.c
46 46
const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
47 47
const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
48 48

  
49
static uint8_t *tb_ret_addr;
50

  
49 51
static void patch_reloc(uint8_t *code_ptr, int type, 
50 52
                        tcg_target_long value, tcg_target_long addend)
51 53
{
......
879 881
    switch(opc) {
880 882
    case INDEX_op_exit_tb:
881 883
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
882
        tcg_out8(s, 0xc3); /* ret */
884
        tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
885
        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
883 886
        break;
884 887
    case INDEX_op_goto_tb:
885 888
        if (s->tb_jmp_offset) {
......
1145 1148
    { -1 },
1146 1149
};
1147 1150

  
1151
static int tcg_target_callee_save_regs[] = {
1152
    /*    TCG_REG_EBP, */ /* currently used for the global env, so no
1153
                             need to save */
1154
    TCG_REG_EBX,
1155
    TCG_REG_ESI,
1156
    TCG_REG_EDI,
1157
};
1158

  
1159
static inline void tcg_out_push(TCGContext *s, int reg)
1160
{
1161
    tcg_out_opc(s, 0x50 + reg);
1162
}
1163

  
1164
static inline void tcg_out_pop(TCGContext *s, int reg)
1165
{
1166
    tcg_out_opc(s, 0x58 + reg);
1167
}
1168

  
1169
/* Generate global QEMU prologue and epilogue code */
1170
void tcg_target_qemu_prologue(TCGContext *s)
1171
{
1172
    int i, frame_size, push_size, stack_addend;
1173
    
1174
    /* TB prologue */
1175
    /* save all callee saved registers */
1176
    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1177
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
1178
    }
1179
    /* reserve some stack space */
1180
    push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1181
    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1182
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
1183
        ~(TCG_TARGET_STACK_ALIGN - 1);
1184
    stack_addend = frame_size - push_size;
1185
    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1186

  
1187
    tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
1188
    
1189
    /* TB epilogue */
1190
    tb_ret_addr = s->code_ptr;
1191
    tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1192
    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1193
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1194
    }
1195
    tcg_out8(s, 0xc3); /* ret */
1196
}
1197

  
1148 1198
void tcg_target_init(TCGContext *s)
1149 1199
{
1150 1200
    /* fail safe */
b/tcg/tcg.c
242 242
    }
243 243
    
244 244
    tcg_target_init(s);
245

  
246
    /* init global prologue and epilogue */
247
    s->code_buf = code_gen_prologue;
248
    s->code_ptr = s->code_buf;
249
    tcg_target_qemu_prologue(s);
250
    flush_icache_range((unsigned long)s->code_buf, 
251
                       (unsigned long)s->code_ptr);
245 252
}
246 253

  
247 254
void tcg_set_frame(TCGContext *s, int reg,
......
680 687
            nb_oargs = arg >> 16;
681 688
            nb_iargs = arg & 0xffff;
682 689
            nb_cargs = def->nb_cargs;
683
        } else if (c == INDEX_op_nopn) {
684
            /* variable number of arguments */
685
            nb_cargs = *args;
686
            nb_oargs = 0;
687
            nb_iargs = 0;
688
        } else {
689
            nb_oargs = def->nb_oargs;
690
            nb_iargs = def->nb_iargs;
691
            nb_cargs = def->nb_cargs;
692
        }
693 690

  
694
        k = 0;
695
        for(i = 0; i < nb_oargs; i++) {
696
            if (k != 0)
697
                fprintf(outfile, ",");
698
            fprintf(outfile, "%s",
699
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
700
        }
701
        for(i = 0; i < nb_iargs; i++) {
702
            if (k != 0)
703
                fprintf(outfile, ",");
691
            /* function name */
704 692
            /* XXX: dump helper name for call */
705 693
            fprintf(outfile, "%s",
706
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
707
        }
708
        for(i = 0; i < nb_cargs; i++) {
709
            if (k != 0)
694
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
695
            /* flags */
696
            fprintf(outfile, ",$0x%" TCG_PRIlx,
697
                    args[nb_oargs + nb_iargs]);
698
            /* nb out args */
699
            fprintf(outfile, ",$%d", nb_oargs);
700
            for(i = 0; i < nb_oargs; i++) {
701
                fprintf(outfile, ",");
702
                fprintf(outfile, "%s",
703
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
704
            }
705
            for(i = 0; i < (nb_iargs - 1); i++) {
710 706
                fprintf(outfile, ",");
711
            arg = args[k++];
712
            fprintf(outfile, "$0x%" TCG_PRIlx, arg);
707
                fprintf(outfile, "%s",
708
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
709
            }
710
        } else {
711
            if (c == INDEX_op_nopn) {
712
                /* variable number of arguments */
713
                nb_cargs = *args;
714
                nb_oargs = 0;
715
                nb_iargs = 0;
716
            } else {
717
                nb_oargs = def->nb_oargs;
718
                nb_iargs = def->nb_iargs;
719
                nb_cargs = def->nb_cargs;
720
            }
721
            
722
            k = 0;
723
            for(i = 0; i < nb_oargs; i++) {
724
                if (k != 0)
725
                    fprintf(outfile, ",");
726
                fprintf(outfile, "%s",
727
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
728
            }
729
            for(i = 0; i < nb_iargs; i++) {
730
                if (k != 0)
731
                    fprintf(outfile, ",");
732
                fprintf(outfile, "%s",
733
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
734
            }
735
            for(i = 0; i < nb_cargs; i++) {
736
                if (k != 0)
737
                    fprintf(outfile, ",");
738
                arg = args[k++];
739
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
740
            }
713 741
        }
714 742
        fprintf(outfile, "\n");
715 743
        args += nb_iargs + nb_oargs + nb_cargs;
......
1027 1055
                    /* if end of basic block, update */
1028 1056
                    if (def->flags & TCG_OPF_BB_END) {
1029 1057
                        tcg_la_bb_end(s, dead_temps);
1058
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1059
                        /* globals are live */
1060
                        memset(dead_temps, 0, s->nb_globals);
1030 1061
                    }
1031 1062
                    
1032 1063
                    /* input args are live */
......
1119 1150
                ts->reg != reg) {
1120 1151
                printf("Inconsistency for register %s:\n", 
1121 1152
                       tcg_target_reg_names[reg]);
1122
                printf("reg state:\n");
1123
                dump_regs(s);
1124
                tcg_abort();
1153
                goto fail;
1125 1154
            }
1126 1155
        }
1127 1156
    }
......
1132 1161
            s->reg_to_temp[ts->reg] != k) {
1133 1162
                printf("Inconsistency for temp %s:\n", 
1134 1163
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1164
        fail:
1135 1165
                printf("reg state:\n");
1136 1166
                dump_regs(s);
1137 1167
                tcg_abort();
1138 1168
        }
1169
        if (ts->val_type == TEMP_VAL_CONST && k < s->nb_globals) {
1170
            printf("constant forbidden in global %s\n",
1171
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1172
            goto fail;
1173
        }
1139 1174
    }
1140 1175
}
1141 1176
#endif
......
1376 1411
        }
1377 1412
    }
1378 1413

  
1379
    /* XXX: permit generic clobber register list ? */ 
1380 1414
    if (def->flags & TCG_OPF_CALL_CLOBBER) {
1415
        /* XXX: permit generic clobber register list ? */ 
1381 1416
        for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1382 1417
            if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1383 1418
                tcg_reg_free(s, reg);
1384 1419
            }
1385 1420
        }
1421
        /* XXX: for load/store we could do that only for the slow path
1422
           (i.e. when a memory callback is called) */
1423

  
1424
        /* store globals and free associated registers (we assume the insn
1425
           can modify any global. */
1426
        for(i = 0; i < s->nb_globals; i++) {
1427
            ts = &s->temps[i];
1428
            if (!ts->fixed_reg) {
1429
                if (ts->val_type == TEMP_VAL_REG) {
1430
                    tcg_reg_free(s, ts->reg);
1431
                }
1432
            }
1433
        }
1386 1434
    }
1387 1435

  
1388 1436
    /* satisfy the output constraints */
......
1435 1483
    }
1436 1484
}
1437 1485

  
1486
#ifdef TCG_TARGET_STACK_GROWSUP
1487
#define STACK_DIR(x) (-(x))
1488
#else
1489
#define STACK_DIR(x) (x)
1490
#endif
1491

  
1438 1492
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1439 1493
                              int opc, const TCGArg *args,
1440 1494
                              unsigned int dead_iargs)
......
1443 1497
    TCGArg arg, func_arg;
1444 1498
    TCGTemp *ts;
1445 1499
    tcg_target_long stack_offset, call_stack_size, func_addr;
1446
    int const_func_arg;
1500
    int const_func_arg, allocate_args;
1447 1501
    TCGRegSet allocated_regs;
1448 1502
    const TCGArgConstraint *arg_ct;
1449 1503

  
......
1464 1518
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1465 1519
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1466 1520
        ~(TCG_TARGET_STACK_ALIGN - 1);
1467
#ifdef TCG_TARGET_STACK_GROWSUP
1468
    tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
1469
#else
1470
    tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
1471
#endif
1472

  
1521
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1522
    if (allocate_args) {
1523
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1524
    }
1525
    /* XXX: on some architectures it does not start at zero */
1473 1526
    stack_offset = 0;
1474 1527
    for(i = nb_regs; i < nb_params; i++) {
1475 1528
        arg = args[nb_oargs + i];
......
1491 1544
        } else {
1492 1545
            tcg_abort();
1493 1546
        }
1494
#ifdef TCG_TARGET_STACK_GROWSUP
1495
        stack_offset -= sizeof(tcg_target_long);
1496
#else
1497
        stack_offset += sizeof(tcg_target_long);
1498
#endif
1547
        /* XXX: not necessarily in the same order */
1548
        stack_offset += STACK_DIR(sizeof(tcg_target_long));
1499 1549
    }
1500 1550
    
1501 1551
    /* assign input registers */
......
1525 1575
    arg_ct = &def->args_ct[0];
1526 1576
    ts = &s->temps[func_arg];
1527 1577
    func_addr = ts->val;
1528
#ifdef HOST_HPPA
1529
    func_addr = (tcg_target_long)__canonicalize_funcptr_for_compare((void *)func_addr);
1530
#endif
1531 1578
    const_func_arg = 0;
1532 1579
    if (ts->val_type == TEMP_VAL_MEM) {
1533 1580
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
......
1586 1633

  
1587 1634
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1588 1635
    
1589
#ifdef TCG_TARGET_STACK_GROWSUP
1590
    tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
1591
#else
1592
    tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
1593
#endif
1636
    if (allocate_args) {
1637
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1638
    }
1594 1639

  
1595 1640
    /* assign output registers and emit moves if needed */
1596 1641
    for(i = 0; i < nb_oargs; i++) {
......
1672 1717
    args = gen_opparam_buf;
1673 1718
    op_index = 0;
1674 1719

  
1675
#ifdef TCG_TARGET_NEEDS_PROLOGUE
1676
    tcg_target_prologue(s);
1677
#endif
1678

  
1679 1720
    for(;;) {
1680 1721
        opc = gen_opc_buf[op_index];
1681 1722
#ifdef CONFIG_PROFILER
b/tcg/tcg.h
90 90

  
91 91
#define TCG_MAX_TEMPS 512
92 92

  
93
/* when the size of the arguments of a called function is smaller than
94
   this value, they are statically allocated in the TB stack frame */
95
#define TCG_STATIC_CALL_ARGS_SIZE 128
96

  
93 97
typedef int TCGType;
94 98

  
95 99
#define TCG_TYPE_I32 0
......
285 289

  
286 290
#define TCG_OPF_BB_END     0x01 /* instruction defines the end of a basic
287 291
                                   block */
288
#define TCG_OPF_CALL_CLOBBER 0x02 /* instruction clobbers call registers */
289
#define TCG_OPF_SIDE_EFFECTS 0x04 /* instruction has side effects */
292
#define TCG_OPF_CALL_CLOBBER 0x02 /* instruction clobbers call registers 
293
                                   and potentially update globals. */
294
#define TCG_OPF_SIDE_EFFECTS 0x04 /* instruction has side effects : it
295
                                     cannot be removed if its output
296
                                     are not used */
290 297

  
291 298
typedef struct TCGOpDef {
292 299
    const char *name;
......
305 312
extern TCGOpDef tcg_op_defs[];
306 313

  
307 314
void tcg_target_init(TCGContext *s);
315
void tcg_target_qemu_prologue(TCGContext *s);
308 316

  
309 317
#define tcg_abort() \
310 318
do {\
......
358 366
int64_t tcg_helper_rem_i64(int64_t arg1, int64_t arg2);
359 367
uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2);
360 368
uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2);
369

  
370
extern uint8_t code_gen_prologue[];
371
#define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr)
b/tcg/x86_64/tcg-target.c
73 73
    TCG_REG_RDX 
74 74
};
75 75

  
76
static uint8_t *tb_ret_addr;
77

  
76 78
static void patch_reloc(uint8_t *code_ptr, int type, 
77 79
                        tcg_target_long value, tcg_target_long addend)
78 80
{
......
841 843
    switch(opc) {
842 844
    case INDEX_op_exit_tb:
843 845
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]);
844
        tcg_out8(s, 0xc3); /* ret */
846
        tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
847
        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
845 848
        break;
846 849
    case INDEX_op_goto_tb:
847 850
        if (s->tb_jmp_offset) {
......
1129 1132
    }
1130 1133
}
1131 1134

  
1135
static int tcg_target_callee_save_regs[] = {
1136
    TCG_REG_R10,
1137
    TCG_REG_R11,
1138
    TCG_REG_RBP,
1139
    TCG_REG_RBX,
1140
    TCG_REG_R12,
1141
    TCG_REG_R13,
1142
    /*    TCG_REG_R14, */ /* currently used for the global env, so no
1143
                             need to save */
1144
    TCG_REG_R15,
1145
};
1146

  
1147
static inline void tcg_out_push(TCGContext *s, int reg)
1148
{
1149
    tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0);
1150
}
1151

  
1152
static inline void tcg_out_pop(TCGContext *s, int reg)
1153
{
1154
    tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0);
1155
}
1156

  
1157
/* Generate global QEMU prologue and epilogue code */
1158
void tcg_target_qemu_prologue(TCGContext *s)
1159
{
1160
    int i, frame_size, push_size, stack_addend;
1161

  
1162
    /* TB prologue */
1163
    /* save all callee saved registers */
1164
    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1165
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
1166

  
1167
    }
1168
    /* reserve some stack space */
1169
    push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8;
1170
    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1171
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
1172
        ~(TCG_TARGET_STACK_ALIGN - 1);
1173
    stack_addend = frame_size - push_size;
1174
    tcg_out_addi(s, TCG_REG_RSP, -stack_addend);
1175

  
1176
    tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */
1177
    
1178
    /* TB epilogue */
1179
    tb_ret_addr = s->code_ptr;
1180
    tcg_out_addi(s, TCG_REG_RSP, stack_addend);
1181
    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1182
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1183
    }
1184
    tcg_out8(s, 0xc3); /* ret */
1185
}
1186

  
1132 1187
static const TCGTargetOpDef x86_64_op_defs[] = {
1133 1188
    { INDEX_op_exit_tb, { } },
1134 1189
    { INDEX_op_goto_tb, { } },
......
1212 1267

  
1213 1268
void tcg_target_init(TCGContext *s)
1214 1269
{
1270
    /* fail safe */
1271
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1272
        tcg_abort();
1273

  
1215 1274
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1216 1275
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
1217 1276
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
......
1227 1286
    
1228 1287
    tcg_regset_clear(s->reserved_regs);
1229 1288
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP);
1230
    /* XXX: will be suppresed when proper global TB entry code will be
1231
       generated */
1232
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RBX);
1233
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RBP);
1234 1289
    
1235 1290
    tcg_add_target_add_op_defs(x86_64_op_defs);
1236 1291
}

Also available in: Unified diff