|
|
1.1 ! root 1: /* ! 2: * Tiny Code Generator for QEMU ! 3: * ! 4: * Copyright (c) 2008 Fabrice Bellard ! 5: * ! 6: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 7: * of this software and associated documentation files (the "Software"), to deal ! 8: * in the Software without restriction, including without limitation the rights ! 9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 10: * copies of the Software, and to permit persons to whom the Software is ! 11: * furnished to do so, subject to the following conditions: ! 12: * ! 13: * The above copyright notice and this permission notice shall be included in ! 14: * all copies or substantial portions of the Software. ! 15: * ! 16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 22: * THE SOFTWARE. ! 23: */ ! 24: #include "tcg-target.h" ! 25: ! 26: #if TCG_TARGET_REG_BITS == 32 ! 27: typedef int32_t tcg_target_long; ! 28: typedef uint32_t tcg_target_ulong; ! 29: #define TCG_PRIlx PRIx32 ! 30: #define TCG_PRIld PRId32 ! 31: #elif TCG_TARGET_REG_BITS == 64 ! 32: typedef int64_t tcg_target_long; ! 33: typedef uint64_t tcg_target_ulong; ! 34: #define TCG_PRIlx PRIx64 ! 35: #define TCG_PRIld PRId64 ! 36: #else ! 37: #error unsupported ! 38: #endif ! 39: ! 40: #if TCG_TARGET_NB_REGS <= 32 ! 41: typedef uint32_t TCGRegSet; ! 42: #elif TCG_TARGET_NB_REGS <= 64 ! 43: typedef uint64_t TCGRegSet; ! 44: #else ! 45: #error unsupported ! 46: #endif ! 47: ! 48: enum { ! 49: #define DEF(s, n, copy_size) INDEX_op_ ## s, ! 50: #include "tcg-opc.h" ! 51: #undef DEF ! 52: NB_OPS, ! 53: }; ! 54: ! 55: #define tcg_regset_clear(d) (d) = 0 ! 56: #define tcg_regset_set(d, s) (d) = (s) ! 57: #define tcg_regset_set32(d, reg, val32) (d) |= (val32) << (reg) ! 58: #define tcg_regset_set_reg(d, r) (d) |= 1 << (r) ! 59: #define tcg_regset_reset_reg(d, r) (d) &= ~(1 << (r)) ! 60: #define tcg_regset_test_reg(d, r) (((d) >> (r)) & 1) ! 61: #define tcg_regset_or(d, a, b) (d) = (a) | (b) ! 62: #define tcg_regset_and(d, a, b) (d) = (a) & (b) ! 63: #define tcg_regset_andnot(d, a, b) (d) = (a) & ~(b) ! 64: #define tcg_regset_not(d, a) (d) = ~(a) ! 65: ! 66: typedef struct TCGRelocation { ! 67: struct TCGRelocation *next; ! 68: int type; ! 69: uint8_t *ptr; ! 70: tcg_target_long addend; ! 71: } TCGRelocation; ! 72: ! 73: typedef struct TCGLabel { ! 74: int has_value; ! 75: union { ! 76: tcg_target_ulong value; ! 77: TCGRelocation *first_reloc; ! 78: } u; ! 79: } TCGLabel; ! 80: ! 81: typedef struct TCGPool { ! 82: struct TCGPool *next; ! 83: int size; ! 84: uint8_t data[0] __attribute__ ((aligned)); ! 85: } TCGPool; ! 86: ! 87: #define TCG_POOL_CHUNK_SIZE 32768 ! 88: ! 89: #define TCG_MAX_LABELS 512 ! 90: ! 91: #define TCG_MAX_TEMPS 512 ! 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: ! 97: typedef int TCGType; ! 98: ! 99: #define TCG_TYPE_I32 0 ! 100: #define TCG_TYPE_I64 1 ! 101: #define TCG_TYPE_COUNT 2 /* number of different types */ ! 102: ! 103: #if TCG_TARGET_REG_BITS == 32 ! 104: #define TCG_TYPE_PTR TCG_TYPE_I32 ! 105: #else ! 106: #define TCG_TYPE_PTR TCG_TYPE_I64 ! 107: #endif ! 108: ! 109: typedef tcg_target_ulong TCGArg; ! 110: ! 111: /* Define a type and accessor macros for varables. Using a struct is ! 112: nice because it gives some level of type safely. Ideally the compiler ! 113: be able to see through all this. However in practice this is not true, ! 114: expecially on targets with braindamaged ABIs (e.g. i386). ! 115: We use plain int by default to avoid this runtime overhead. ! 116: Users of tcg_gen_* don't need to know about any of this, and should ! 117: treat TCGv as an opaque type. ! 118: In additon we do typechecking for different types of variables. TCGv_i32 ! 119: and TCGv_i64 are 32/64-bit variables respectively. TCGv and TCGv_ptr ! 120: are aliases for target_ulong and host pointer sized values respectively. ! 121: */ ! 122: ! 123: //#define DEBUG_TCGV 1 ! 124: ! 125: #ifdef DEBUG_TCGV ! 126: ! 127: typedef struct ! 128: { ! 129: int i32; ! 130: } TCGv_i32; ! 131: ! 132: typedef struct ! 133: { ! 134: int i64; ! 135: } TCGv_i64; ! 136: ! 137: #define MAKE_TCGV_I32(i) __extension__ \ ! 138: ({ TCGv_i32 make_tcgv_tmp = {i}; make_tcgv_tmp;}) ! 139: #define MAKE_TCGV_I64(i) __extension__ \ ! 140: ({ TCGv_i64 make_tcgv_tmp = {i}; make_tcgv_tmp;}) ! 141: #define GET_TCGV_I32(t) ((t).i32) ! 142: #define GET_TCGV_I64(t) ((t).i64) ! 143: #if TCG_TARGET_REG_BITS == 32 ! 144: #define TCGV_LOW(t) MAKE_TCGV_I32(GET_TCGV_I64(t)) ! 145: #define TCGV_HIGH(t) MAKE_TCGV_I32(GET_TCGV_I64(t) + 1) ! 146: #endif ! 147: ! 148: #else /* !DEBUG_TCGV */ ! 149: ! 150: typedef int TCGv_i32; ! 151: typedef int TCGv_i64; ! 152: #define MAKE_TCGV_I32(x) (x) ! 153: #define MAKE_TCGV_I64(x) (x) ! 154: #define GET_TCGV_I32(t) (t) ! 155: #define GET_TCGV_I64(t) (t) ! 156: #if TCG_TARGET_REG_BITS == 32 ! 157: #define TCGV_LOW(t) (t) ! 158: #define TCGV_HIGH(t) ((t) + 1) ! 159: #endif ! 160: ! 161: #endif /* DEBUG_TCGV */ ! 162: ! 163: /* Dummy definition to avoid compiler warnings. */ ! 164: #define TCGV_UNUSED_I32(x) x = MAKE_TCGV_I32(-1) ! 165: #define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1) ! 166: ! 167: /* call flags */ ! 168: #define TCG_CALL_TYPE_MASK 0x000f ! 169: #define TCG_CALL_TYPE_STD 0x0000 /* standard C call */ ! 170: #define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */ ! 171: #define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */ ! 172: #define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */ ! 173: /* A pure function only reads its arguments and globals variables and ! 174: cannot raise exceptions. Hence a call to a pure function can be ! 175: safely suppressed if the return value is not used. */ ! 176: #define TCG_CALL_PURE 0x0010 ! 177: ! 178: /* used to align parameters */ ! 179: #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1) ! 180: #define TCG_CALL_DUMMY_ARG ((TCGArg)(-1)) ! 181: ! 182: typedef enum { ! 183: TCG_COND_EQ, ! 184: TCG_COND_NE, ! 185: TCG_COND_LT, ! 186: TCG_COND_GE, ! 187: TCG_COND_LE, ! 188: TCG_COND_GT, ! 189: /* unsigned */ ! 190: TCG_COND_LTU, ! 191: TCG_COND_GEU, ! 192: TCG_COND_LEU, ! 193: TCG_COND_GTU, ! 194: } TCGCond; ! 195: ! 196: #define TEMP_VAL_DEAD 0 ! 197: #define TEMP_VAL_REG 1 ! 198: #define TEMP_VAL_MEM 2 ! 199: #define TEMP_VAL_CONST 3 ! 200: ! 201: /* XXX: optimize memory layout */ ! 202: typedef struct TCGTemp { ! 203: TCGType base_type; ! 204: TCGType type; ! 205: int val_type; ! 206: int reg; ! 207: tcg_target_long val; ! 208: int mem_reg; ! 209: tcg_target_long mem_offset; ! 210: unsigned int fixed_reg:1; ! 211: unsigned int mem_coherent:1; ! 212: unsigned int mem_allocated:1; ! 213: unsigned int temp_local:1; /* If true, the temp is saved accross ! 214: basic blocks. Otherwise, it is not ! 215: preserved accross basic blocks. */ ! 216: unsigned int temp_allocated:1; /* never used for code gen */ ! 217: /* index of next free temp of same base type, -1 if end */ ! 218: int next_free_temp; ! 219: const char *name; ! 220: } TCGTemp; ! 221: ! 222: typedef struct TCGHelperInfo { ! 223: tcg_target_ulong func; ! 224: const char *name; ! 225: } TCGHelperInfo; ! 226: ! 227: typedef struct TCGContext TCGContext; ! 228: ! 229: struct TCGContext { ! 230: uint8_t *pool_cur, *pool_end; ! 231: TCGPool *pool_first, *pool_current; ! 232: TCGLabel *labels; ! 233: int nb_labels; ! 234: TCGTemp *temps; /* globals first, temps after */ ! 235: int nb_globals; ! 236: int nb_temps; ! 237: /* index of free temps, -1 if none */ ! 238: int first_free_temp[TCG_TYPE_COUNT * 2]; ! 239: ! 240: /* goto_tb support */ ! 241: uint8_t *code_buf; ! 242: unsigned long *tb_next; ! 243: uint16_t *tb_next_offset; ! 244: uint16_t *tb_jmp_offset; /* != NULL if USE_DIRECT_JUMP */ ! 245: ! 246: /* liveness analysis */ ! 247: uint16_t *op_dead_iargs; /* for each operation, each bit tells if the ! 248: corresponding input argument is dead */ ! 249: ! 250: /* tells in which temporary a given register is. It does not take ! 251: into account fixed registers */ ! 252: int reg_to_temp[TCG_TARGET_NB_REGS]; ! 253: TCGRegSet reserved_regs; ! 254: tcg_target_long current_frame_offset; ! 255: tcg_target_long frame_start; ! 256: tcg_target_long frame_end; ! 257: int frame_reg; ! 258: ! 259: uint8_t *code_ptr; ! 260: TCGTemp static_temps[TCG_MAX_TEMPS]; ! 261: ! 262: TCGHelperInfo *helpers; ! 263: int nb_helpers; ! 264: int allocated_helpers; ! 265: int helpers_sorted; ! 266: ! 267: #ifdef CONFIG_PROFILER ! 268: /* profiling info */ ! 269: int64_t tb_count1; ! 270: int64_t tb_count; ! 271: int64_t op_count; /* total insn count */ ! 272: int op_count_max; /* max insn per TB */ ! 273: int64_t temp_count; ! 274: int temp_count_max; ! 275: int64_t del_op_count; ! 276: int64_t code_in_len; ! 277: int64_t code_out_len; ! 278: int64_t interm_time; ! 279: int64_t code_time; ! 280: int64_t la_time; ! 281: int64_t restore_count; ! 282: int64_t restore_time; ! 283: #endif ! 284: }; ! 285: ! 286: extern TCGContext tcg_ctx; ! 287: extern uint16_t *gen_opc_ptr; ! 288: extern TCGArg *gen_opparam_ptr; ! 289: extern uint16_t gen_opc_buf[]; ! 290: extern TCGArg gen_opparam_buf[]; ! 291: ! 292: /* pool based memory allocation */ ! 293: ! 294: void *tcg_malloc_internal(TCGContext *s, int size); ! 295: void tcg_pool_reset(TCGContext *s); ! 296: void tcg_pool_delete(TCGContext *s); ! 297: ! 298: static inline void *tcg_malloc(int size) ! 299: { ! 300: TCGContext *s = &tcg_ctx; ! 301: uint8_t *ptr, *ptr_end; ! 302: size = (size + sizeof(long) - 1) & ~(sizeof(long) - 1); ! 303: ptr = s->pool_cur; ! 304: ptr_end = ptr + size; ! 305: if (unlikely(ptr_end > s->pool_end)) { ! 306: return tcg_malloc_internal(&tcg_ctx, size); ! 307: } else { ! 308: s->pool_cur = ptr_end; ! 309: return ptr; ! 310: } ! 311: } ! 312: ! 313: void tcg_context_init(TCGContext *s); ! 314: void tcg_func_start(TCGContext *s); ! 315: ! 316: int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf); ! 317: int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset); ! 318: ! 319: void tcg_set_frame(TCGContext *s, int reg, ! 320: tcg_target_long start, tcg_target_long size); ! 321: ! 322: TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name); ! 323: TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset, ! 324: const char *name); ! 325: TCGv_i32 tcg_temp_new_internal_i32(int temp_local); ! 326: static inline TCGv_i32 tcg_temp_new_i32(void) ! 327: { ! 328: return tcg_temp_new_internal_i32(0); ! 329: } ! 330: static inline TCGv_i32 tcg_temp_local_new_i32(void) ! 331: { ! 332: return tcg_temp_new_internal_i32(1); ! 333: } ! 334: void tcg_temp_free_i32(TCGv_i32 arg); ! 335: char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg); ! 336: ! 337: TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name); ! 338: TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset, ! 339: const char *name); ! 340: TCGv_i64 tcg_temp_new_internal_i64(int temp_local); ! 341: static inline TCGv_i64 tcg_temp_new_i64(void) ! 342: { ! 343: return tcg_temp_new_internal_i64(0); ! 344: } ! 345: static inline TCGv_i64 tcg_temp_local_new_i64(void) ! 346: { ! 347: return tcg_temp_new_internal_i64(1); ! 348: } ! 349: void tcg_temp_free_i64(TCGv_i64 arg); ! 350: char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg); ! 351: ! 352: void tcg_dump_info(FILE *f, ! 353: int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); ! 354: ! 355: #define TCG_CT_ALIAS 0x80 ! 356: #define TCG_CT_IALIAS 0x40 ! 357: #define TCG_CT_REG 0x01 ! 358: #define TCG_CT_CONST 0x02 /* any constant of register size */ ! 359: ! 360: typedef struct TCGArgConstraint { ! 361: uint16_t ct; ! 362: uint8_t alias_index; ! 363: union { ! 364: TCGRegSet regs; ! 365: } u; ! 366: } TCGArgConstraint; ! 367: ! 368: #define TCG_MAX_OP_ARGS 16 ! 369: ! 370: #define TCG_OPF_BB_END 0x01 /* instruction defines the end of a basic ! 371: block */ ! 372: #define TCG_OPF_CALL_CLOBBER 0x02 /* instruction clobbers call registers ! 373: and potentially update globals. */ ! 374: #define TCG_OPF_SIDE_EFFECTS 0x04 /* instruction has side effects : it ! 375: cannot be removed if its output ! 376: are not used */ ! 377: ! 378: typedef struct TCGOpDef { ! 379: const char *name; ! 380: uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args; ! 381: uint8_t flags; ! 382: uint16_t copy_size; ! 383: TCGArgConstraint *args_ct; ! 384: int *sorted_args; ! 385: } TCGOpDef; ! 386: ! 387: typedef struct TCGTargetOpDef { ! 388: int op; ! 389: const char *args_ct_str[TCG_MAX_OP_ARGS]; ! 390: } TCGTargetOpDef; ! 391: ! 392: void tcg_target_init(TCGContext *s); ! 393: void tcg_target_qemu_prologue(TCGContext *s); ! 394: ! 395: #define tcg_abort() \ ! 396: do {\ ! 397: fprintf(stderr, "%s:%d: tcg fatal error\n", __FILE__, __LINE__);\ ! 398: abort();\ ! 399: } while (0) ! 400: ! 401: void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs); ! 402: ! 403: #if TCG_TARGET_REG_BITS == 32 ! 404: #define tcg_const_ptr tcg_const_i32 ! 405: #define tcg_add_ptr tcg_add_i32 ! 406: #define tcg_sub_ptr tcg_sub_i32 ! 407: #define TCGv_ptr TCGv_i32 ! 408: #define GET_TCGV_PTR GET_TCGV_I32 ! 409: #define tcg_global_reg_new_ptr tcg_global_reg_new_i32 ! 410: #define tcg_global_mem_new_ptr tcg_global_mem_new_i32 ! 411: #define tcg_temp_new_ptr tcg_temp_new_i32 ! 412: #define tcg_temp_free_ptr tcg_temp_free_i32 ! 413: #else ! 414: #define tcg_const_ptr tcg_const_i64 ! 415: #define tcg_add_ptr tcg_add_i64 ! 416: #define tcg_sub_ptr tcg_sub_i64 ! 417: #define TCGv_ptr TCGv_i64 ! 418: #define GET_TCGV_PTR GET_TCGV_I64 ! 419: #define tcg_global_reg_new_ptr tcg_global_reg_new_i64 ! 420: #define tcg_global_mem_new_ptr tcg_global_mem_new_i64 ! 421: #define tcg_temp_new_ptr tcg_temp_new_i64 ! 422: #define tcg_temp_free_ptr tcg_temp_free_i64 ! 423: #endif ! 424: ! 425: void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, ! 426: int sizemask, TCGArg ret, int nargs, TCGArg *args); ! 427: ! 428: void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, ! 429: int c, int right, int arith); ! 430: ! 431: /* only used for debugging purposes */ ! 432: void tcg_register_helper(void *func, const char *name); ! 433: const char *tcg_helper_get_name(TCGContext *s, void *func); ! 434: void tcg_dump_ops(TCGContext *s, FILE *outfile); ! 435: ! 436: void dump_ops(const uint16_t *opc_buf, const TCGArg *opparam_buf); ! 437: TCGv_i32 tcg_const_i32(int32_t val); ! 438: TCGv_i64 tcg_const_i64(int64_t val); ! 439: TCGv_i32 tcg_const_local_i32(int32_t val); ! 440: TCGv_i64 tcg_const_local_i64(int64_t val); ! 441: ! 442: void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, ! 443: int label_index, long addend); ! 444: const TCGArg *tcg_gen_code_op(TCGContext *s, int opc, const TCGArg *args1, ! 445: unsigned int dead_iargs); ! 446: ! 447: /* tcg-runtime.c */ ! 448: int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); ! 449: int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); ! 450: int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); ! 451: int64_t tcg_helper_div_i64(int64_t arg1, int64_t arg2); ! 452: int64_t tcg_helper_rem_i64(int64_t arg1, int64_t arg2); ! 453: uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2); ! 454: uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2); ! 455: ! 456: extern uint8_t code_gen_prologue[]; ! 457: #if defined(_ARCH_PPC) && !defined(_ARCH_PPC64) ! 458: #define tcg_qemu_tb_exec(tb_ptr) \ ! 459: ((long REGPARM __attribute__ ((longcall)) (*)(void *))code_gen_prologue)(tb_ptr) ! 460: #else ! 461: #define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr) ! 462: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.