⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 translate.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
/* *  m68k translation * *  Copyright (c) 2005-2007 CodeSourcery *  Written by Paul Brook * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include "config.h"#include "cpu.h"#include "exec-all.h"#include "disas.h"#include "m68k-qreg.h"//#define DEBUG_DISPATCH 1static inline void qemu_assert(int cond, const char *msg){    if (!cond) {        fprintf (stderr, "badness: %s\n", msg);        abort();    }}/* internal defines */typedef struct DisasContext {    CPUM68KState *env;    target_ulong insn_pc; /* Start of the current instruction.  */    target_ulong pc;    int is_jmp;    int cc_op;    int user;    uint32_t fpcr;    struct TranslationBlock *tb;    int singlestep_enabled;    int is_mem;} DisasContext;#define DISAS_JUMP_NEXT 4#if defined(CONFIG_USER_ONLY)#define IS_USER(s) 1#else#define IS_USER(s) s->user#endif/* XXX: move that elsewhere *//* ??? Fix exceptions.  */static void *gen_throws_exception;#define gen_last_qop NULLstatic uint16_t *gen_opc_ptr;static uint32_t *gen_opparam_ptr;extern FILE *logfile;extern int loglevel;enum {#define DEF(s, n, copy_size) INDEX_op_ ## s,#include "opc.h"#undef DEF    NB_OPS,};#include "gen-op.h"#if defined(CONFIG_USER_ONLY)#define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val)#define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr)#else#define gen_st(s, name, addr, val) do { \    if (IS_USER(s)) \        gen_op_st##name##_user(addr, val); \    else \        gen_op_st##name##_kernel(addr, val); \    } while (0)#define gen_ld(s, name, val, addr) do { \    if (IS_USER(s)) \        gen_op_ld##name##_user(val, addr); \    else \        gen_op_ld##name##_kernel(val, addr); \    } while (0)#endif#include "op-hacks.h"#define OS_BYTE 0#define OS_WORD 1#define OS_LONG 2#define OS_SINGLE 4#define OS_DOUBLE 5#define DREG(insn, pos) (((insn >> pos) & 7) + QREG_D0)#define AREG(insn, pos) (((insn >> pos) & 7) + QREG_A0)#define FREG(insn, pos) (((insn >> pos) & 7) + QREG_F0)typedef void (*disas_proc)(DisasContext *, uint16_t);#ifdef DEBUG_DISPATCH#define DISAS_INSN(name) \  static void real_disas_##name (DisasContext *s, uint16_t insn); \  static void disas_##name (DisasContext *s, uint16_t insn) { \    if (logfile) fprintf(logfile, "Dispatch " #name "\n"); \    real_disas_##name(s, insn); } \  static void real_disas_##name (DisasContext *s, uint16_t insn)#else#define DISAS_INSN(name) \  static void disas_##name (DisasContext *s, uint16_t insn)#endif/* Generate a load from the specified address.  Narrow values are   sign extended to full register width.  */static inline int gen_load(DisasContext * s, int opsize, int addr, int sign){    int tmp;    s->is_mem = 1;    switch(opsize) {    case OS_BYTE:        tmp = gen_new_qreg(QMODE_I32);        if (sign)            gen_ld(s, 8s32, tmp, addr);        else            gen_ld(s, 8u32, tmp, addr);        break;    case OS_WORD:        tmp = gen_new_qreg(QMODE_I32);        if (sign)            gen_ld(s, 16s32, tmp, addr);        else            gen_ld(s, 16u32, tmp, addr);        break;    case OS_LONG:        tmp = gen_new_qreg(QMODE_I32);        gen_ld(s, 32, tmp, addr);        break;    case OS_SINGLE:        tmp = gen_new_qreg(QMODE_F32);        gen_ld(s, f32, tmp, addr);        break;    case OS_DOUBLE:        tmp  = gen_new_qreg(QMODE_F64);        gen_ld(s, f64, tmp, addr);        break;    default:        qemu_assert(0, "bad load size");    }    gen_throws_exception = gen_last_qop;    return tmp;}/* Generate a store.  */static inline void gen_store(DisasContext *s, int opsize, int addr, int val){    s->is_mem = 1;    switch(opsize) {    case OS_BYTE:        gen_st(s, 8, addr, val);        break;    case OS_WORD:        gen_st(s, 16, addr, val);        break;    case OS_LONG:        gen_st(s, 32, addr, val);        break;    case OS_SINGLE:        gen_st(s, f32, addr, val);        break;    case OS_DOUBLE:        gen_st(s, f64, addr, val);        break;    default:        qemu_assert(0, "bad store size");    }    gen_throws_exception = gen_last_qop;}/* Generate an unsigned load if VAL is 0 a signed load if val is -1,   otherwise generate a store.  */static int gen_ldst(DisasContext *s, int opsize, int addr, int val){    if (val > 0) {        gen_store(s, opsize, addr, val);        return 0;    } else {        return gen_load(s, opsize, addr, val != 0);    }}/* Read a 32-bit immediate constant.  */static inline uint32_t read_im32(DisasContext *s){    uint32_t im;    im = ((uint32_t)lduw_code(s->pc)) << 16;    s->pc += 2;    im |= lduw_code(s->pc);    s->pc += 2;    return im;}/* Calculate and address index.  */static int gen_addr_index(uint16_t ext, int tmp){    int add;    int scale;    add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);    if ((ext & 0x800) == 0) {        gen_op_ext16s32(tmp, add);        add = tmp;    }    scale = (ext >> 9) & 3;    if (scale != 0) {        gen_op_shl32(tmp, add, gen_im32(scale));        add = tmp;    }    return add;}/* Handle a base + index + displacement effective addresss.  A base of   -1 means pc-relative.  */static int gen_lea_indexed(DisasContext *s, int opsize, int base){    uint32_t offset;    uint16_t ext;    int add;    int tmp;    uint32_t bd, od;    offset = s->pc;    ext = lduw_code(s->pc);    s->pc += 2;    if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))        return -1;    if (ext & 0x100) {        /* full extension word format */        if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))            return -1;        if ((ext & 0x30) > 0x10) {            /* base displacement */            if ((ext & 0x30) == 0x20) {                bd = (int16_t)lduw_code(s->pc);                s->pc += 2;            } else {                bd = read_im32(s);            }        } else {            bd = 0;        }        tmp = gen_new_qreg(QMODE_I32);        if ((ext & 0x44) == 0) {            /* pre-index */            add = gen_addr_index(ext, tmp);        } else {            add = QREG_NULL;        }        if ((ext & 0x80) == 0) {            /* base not suppressed */            if (base == -1) {                base = gen_im32(offset + bd);                bd = 0;            }            if (add) {                gen_op_add32(tmp, add, base);                add = tmp;            } else {                add = base;            }        }        if (add) {            if (bd != 0) {                gen_op_add32(tmp, add, gen_im32(bd));                add = tmp;            }        } else {            add = gen_im32(bd);        }        if ((ext & 3) != 0) {            /* memory indirect */            base = gen_load(s, OS_LONG, add, 0);            if ((ext & 0x44) == 4) {                add = gen_addr_index(ext, tmp);                gen_op_add32(tmp, add, base);                add = tmp;            } else {                add = base;            }            if ((ext & 3) > 1) {                /* outer displacement */                if ((ext & 3) == 2) {                    od = (int16_t)lduw_code(s->pc);                    s->pc += 2;                } else {                    od = read_im32(s);                }            } else {                od = 0;            }            if (od != 0) {                gen_op_add32(tmp, add, gen_im32(od));                add = tmp;            }        }    } else {        /* brief extension word format */        tmp = gen_new_qreg(QMODE_I32);        add = gen_addr_index(ext, tmp);        if (base != -1) {            gen_op_add32(tmp, add, base);            if ((int8_t)ext)                gen_op_add32(tmp, tmp, gen_im32((int8_t)ext));        } else {            gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));        }        add = tmp;    }    return add;}/* Update the CPU env CC_OP state.  */static inline void gen_flush_cc_op(DisasContext *s){    if (s->cc_op != CC_OP_DYNAMIC)        gen_op_mov32(QREG_CC_OP, gen_im32(s->cc_op));}/* Evaluate all the CC flags.  */static inline void gen_flush_flags(DisasContext *s){    if (s->cc_op == CC_OP_FLAGS)        return;    gen_flush_cc_op(s);    gen_op_flush_flags();    s->cc_op = CC_OP_FLAGS;}static inline int opsize_bytes(int opsize){    switch (opsize) {    case OS_BYTE: return 1;    case OS_WORD: return 2;    case OS_LONG: return 4;    case OS_SINGLE: return 4;    case OS_DOUBLE: return 8;    default:        qemu_assert(0, "bad operand size");    }}/* Assign value to a register.  If the width is less than the register width   only the low part of the register is set.  */static void gen_partset_reg(int opsize, int reg, int val){    int tmp;    switch (opsize) {    case OS_BYTE:        gen_op_and32(reg, reg, gen_im32(0xffffff00));        tmp = gen_new_qreg(QMODE_I32);        gen_op_and32(tmp, val, gen_im32(0xff));        gen_op_or32(reg, reg, tmp);        break;    case OS_WORD:        gen_op_and32(reg, reg, gen_im32(0xffff0000));        tmp = gen_new_qreg(QMODE_I32);        gen_op_and32(tmp, val, gen_im32(0xffff));        gen_op_or32(reg, reg, tmp);        break;    case OS_LONG:        gen_op_mov32(reg, val);        break;    case OS_SINGLE:        gen_op_pack_32_f32(reg, val);        break;    default:        qemu_assert(0, "Bad operand size");        break;    }}/* Sign or zero extend a value.  */static inline int gen_extend(int val, int opsize, int sign){    int tmp;    switch (opsize) {    case OS_BYTE:        tmp = gen_new_qreg(QMODE_I32);        if (sign)            gen_op_ext8s32(tmp, val);        else            gen_op_ext8u32(tmp, val);        break;    case OS_WORD:        tmp = gen_new_qreg(QMODE_I32);        if (sign)            gen_op_ext16s32(tmp, val);        else            gen_op_ext16u32(tmp, val);        break;    case OS_LONG:        tmp = val;        break;    case OS_SINGLE:        tmp = gen_new_qreg(QMODE_F32);        gen_op_pack_f32_32(tmp, val);        break;    default:        qemu_assert(0, "Bad operand size");    }    return tmp;}/* Generate code for an "effective address".  Does not adjust the base   register for autoincrememnt addressing modes.  */static int gen_lea(DisasContext *s, uint16_t insn, int opsize){    int reg;    int tmp;    uint16_t ext;    uint32_t offset;    reg = insn & 7;    switch ((insn >> 3) & 7) {    case 0: /* Data register direct.  */    case 1: /* Address register direct.  */        return -1;    case 2: /* Indirect register */    case 3: /* Indirect postincrement.  */        reg += QREG_A0;        return reg;    case 4: /* Indirect predecrememnt.  */        reg += QREG_A0;        tmp = gen_new_qreg(QMODE_I32);        gen_op_sub32(tmp, reg, gen_im32(opsize_bytes(opsize)));        return tmp;    case 5: /* Indirect displacement.  */        reg += QREG_A0;        tmp = gen_new_qreg(QMODE_I32);        ext = lduw_code(s->pc);        s->pc += 2;        gen_op_add32(tmp, reg, gen_im32((int16_t)ext));        return tmp;    case 6: /* Indirect index + displacement.  */        reg += QREG_A0;        return gen_lea_indexed(s, opsize, reg);    case 7: /* Other */        switch (reg) {        case 0: /* Absolute short.  */            offset = ldsw_code(s->pc);            s->pc += 2;            return gen_im32(offset);        case 1: /* Absolute long.  */            offset = read_im32(s);            return gen_im32(offset);        case 2: /* pc displacement  */            tmp = gen_new_qreg(QMODE_I32);            offset = s->pc;            offset += ldsw_code(s->pc);            s->pc += 2;            return gen_im32(offset);        case 3: /* pc index+displacement.  */            return gen_lea_indexed(s, opsize, -1);        case 4: /* Immediate.  */        default:            return -1;        }    }    /* Should never happen.  */    return -1;}/* Helper function for gen_ea. Reuse the computed address between the   for read/write operands.  */static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,                              int val, int *addrp){    int tmp;    if (addrp && val > 0) {        tmp = *addrp;    } else {        tmp = gen_lea(s, insn, opsize);        if (tmp == -1)            return -1;        if (addrp)            *addrp = tmp;    }    return gen_ldst(s, opsize, tmp, val);}/* Generate code to load/store a value ito/from an EA.  If VAL > 0 this is   a write otherwise it is a read (0 == sign extend, -1 == zero extend).   ADDRP is non-null for readwrite operands.  */static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,                  int *addrp){    int reg;    int result;    uint32_t offset;    reg = insn & 7;    switch ((insn >> 3) & 7) {    case 0: /* Data register direct.  */        reg += QREG_D0;        if (val > 0) {            gen_partset_reg(opsize, reg, val);            return 0;        } else {            return gen_extend(reg, opsize, val);        }    case 1: /* Address register direct.  */        reg += QREG_A0;        if (val > 0) {            gen_op_mov32(reg, val);            return 0;        } else {            return gen_extend(reg, opsize, val);        }    case 2: /* Indirect register */        reg += QREG_A0;        return gen_ldst(s, opsize, reg, val);    case 3: /* Indirect postincrement.  */        reg += QREG_A0;        result = gen_ldst(s, opsize, reg, val);        /* ??? This is not exception safe.  The instruction may still           fault after this point.  */        if (val > 0 || !addrp)            gen_op_add32(reg, reg, gen_im32(opsize_bytes(opsize)));        return result;

⌨️ 快捷键说明

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