Annotation of qemu/target-microblaze/op_helper.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  *  Microblaze helper routines.
                      3:  *
                      4:  *  Copyright (c) 2009 Edgar E. Iglesias <[email protected]>.
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
                     18:  */
                     19: 
                     20: #include <assert.h>
                     21: #include "exec.h"
                     22: #include "helper.h"
                     23: #include "host-utils.h"
                     24: 
                     25: #define D(x)
                     26: 
                     27: #if !defined(CONFIG_USER_ONLY)
                     28: #define MMUSUFFIX _mmu
                     29: #define SHIFT 0
                     30: #include "softmmu_template.h"
                     31: #define SHIFT 1
                     32: #include "softmmu_template.h"
                     33: #define SHIFT 2
                     34: #include "softmmu_template.h"
                     35: #define SHIFT 3
                     36: #include "softmmu_template.h"
                     37: 
                     38: /* Try to fill the TLB and return an exception if error. If retaddr is
                     39:    NULL, it means that the function was called in C code (i.e. not
                     40:    from generated code or from helper.c) */
                     41: /* XXX: fix it to restore all registers */
                     42: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
                     43: {
                     44:     TranslationBlock *tb;
                     45:     CPUState *saved_env;
                     46:     unsigned long pc;
                     47:     int ret;
                     48: 
                     49:     /* XXX: hack to restore env in all cases, even if not called from
                     50:        generated code */
                     51:     saved_env = env;
                     52:     env = cpu_single_env;
                     53: 
                     54:     ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
                     55:     if (unlikely(ret)) {
                     56:         if (retaddr) {
                     57:             /* now we have a real cpu fault */
                     58:             pc = (unsigned long)retaddr;
                     59:             tb = tb_find_pc(pc);
                     60:             if (tb) {
                     61:                 /* the PC is inside the translated code. It means that we have
                     62:                    a virtual CPU fault */
                     63:                 cpu_restore_state(tb, env, pc, NULL);
                     64:             }
                     65:         }
                     66:         cpu_loop_exit();
                     67:     }
                     68:     env = saved_env;
                     69: }
                     70: #endif
                     71: 
                     72: void helper_raise_exception(uint32_t index)
                     73: {
                     74:     env->exception_index = index;
                     75:     cpu_loop_exit();
                     76: }
                     77: 
                     78: void helper_debug(void)
                     79: {
                     80:     int i;
                     81: 
                     82:     qemu_log("PC=%8.8x\n", env->sregs[SR_PC]);
1.1.1.3 ! root       83:     qemu_log("rmsr=%x resr=%x rear=%x debug[%x] imm=%x iflags=%x\n",
        !            84:              env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
        !            85:              env->debug, env->imm, env->iflags);
        !            86:     qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
        !            87:              env->btaken, env->btarget,
        !            88:              (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
        !            89:              (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
        !            90:              (env->sregs[SR_MSR] & MSR_EIP),
        !            91:              (env->sregs[SR_MSR] & MSR_IE));
1.1       root       92:     for (i = 0; i < 32; i++) {
                     93:         qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
                     94:         if ((i + 1) % 4 == 0)
                     95:             qemu_log("\n");
                     96:     }
                     97:     qemu_log("\n\n");
                     98: }
                     99: 
                    100: static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin)
                    101: {
                    102:     uint32_t cout = 0;
                    103: 
                    104:     if ((b == ~0) && cin)
                    105:         cout = 1;
                    106:     else if ((~0 - a) < (b + cin))
                    107:         cout = 1;
                    108:     return cout;
                    109: }
                    110: 
                    111: uint32_t helper_cmp(uint32_t a, uint32_t b)
                    112: {
                    113:     uint32_t t;
                    114: 
                    115:     t = b + ~a + 1;
                    116:     if ((b & 0x80000000) ^ (a & 0x80000000))
                    117:         t = (t & 0x7fffffff) | (b & 0x80000000);
                    118:     return t;
                    119: }
                    120: 
                    121: uint32_t helper_cmpu(uint32_t a, uint32_t b)
                    122: {
                    123:     uint32_t t;
                    124: 
                    125:     t = b + ~a + 1;
                    126:     if ((b & 0x80000000) ^ (a & 0x80000000))
                    127:         t = (t & 0x7fffffff) | (a & 0x80000000);
                    128:     return t;
                    129: }
                    130: 
                    131: uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
                    132: {
                    133:     uint32_t d, cf = 0, ncf;
                    134: 
                    135:     if (c)
                    136:         cf = env->sregs[SR_MSR] >> 31;
                    137:     assert(cf == 0 || cf == 1);
                    138:     d = a + b + cf;
                    139: 
                    140:     if (!k) {
                    141:         ncf = compute_carry(a, b, cf);
                    142:         assert(ncf == 0 || ncf == 1);
                    143:         if (ncf)
                    144:             env->sregs[SR_MSR] |= MSR_C | MSR_CC;
                    145:         else
                    146:             env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
                    147:     }
                    148:     D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
                    149:                d, a, b, cf, ncf, k, c));
                    150:     return d;
                    151: }
                    152: 
                    153: uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
                    154: {
                    155:     uint32_t d, cf = 1, ncf;
                    156: 
                    157:     if (c)
                    158:         cf = env->sregs[SR_MSR] >> 31; 
                    159:     assert(cf == 0 || cf == 1);
                    160:     d = b + ~a + cf;
                    161: 
                    162:     if (!k) {
                    163:         ncf = compute_carry(b, ~a, cf);
                    164:         assert(ncf == 0 || ncf == 1);
                    165:         if (ncf)
                    166:             env->sregs[SR_MSR] |= MSR_C | MSR_CC;
                    167:         else
                    168:             env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
                    169:     }
                    170:     D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
                    171:                d, a, b, cf, ncf, k, c));
                    172:     return d;
                    173: }
                    174: 
                    175: static inline int div_prepare(uint32_t a, uint32_t b)
                    176: {
                    177:     if (b == 0) {
                    178:         env->sregs[SR_MSR] |= MSR_DZ;
1.1.1.2   root      179: 
                    180:         if ((env->sregs[SR_MSR] & MSR_EE)
                    181:             && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) {
                    182:             env->sregs[SR_ESR] = ESR_EC_DIVZERO;
                    183:             helper_raise_exception(EXCP_HW_EXCP);
                    184:         }
1.1       root      185:         return 0;
                    186:     }
                    187:     env->sregs[SR_MSR] &= ~MSR_DZ;
                    188:     return 1;
                    189: }
                    190: 
                    191: uint32_t helper_divs(uint32_t a, uint32_t b)
                    192: {
                    193:     if (!div_prepare(a, b))
                    194:         return 0;
                    195:     return (int32_t)a / (int32_t)b;
                    196: }
                    197: 
                    198: uint32_t helper_divu(uint32_t a, uint32_t b)
                    199: {
                    200:     if (!div_prepare(a, b))
                    201:         return 0;
                    202:     return a / b;
                    203: }
                    204: 
                    205: uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
                    206: {
                    207:     unsigned int i;
                    208:     uint32_t mask = 0xff000000;
                    209: 
                    210:     for (i = 0; i < 4; i++) {
                    211:         if ((a & mask) == (b & mask))
                    212:             return i + 1;
                    213:         mask >>= 8;
                    214:     }
                    215:     return 0;
                    216: }
                    217: 
1.1.1.2   root      218: void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
                    219: {
                    220:     if (addr & mask) {
                    221:             qemu_log_mask(CPU_LOG_INT,
                    222:                           "unaligned access addr=%x mask=%x, wr=%d dr=r%d\n",
                    223:                           addr, mask, wr, dr);
                    224:             env->sregs[SR_EAR] = addr;
                    225:             env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \
                    226:                                  | (dr & 31) << 5;
                    227:             if (mask == 3) {
                    228:                 env->sregs[SR_ESR] |= 1 << 11;
                    229:             }
                    230:             if (!(env->sregs[SR_MSR] & MSR_EE)) {
                    231:                 return;
                    232:             }
                    233:             helper_raise_exception(EXCP_HW_EXCP);
                    234:     }
                    235: }
                    236: 
1.1       root      237: #if !defined(CONFIG_USER_ONLY)
                    238: /* Writes/reads to the MMU's special regs end up here.  */
                    239: uint32_t helper_mmu_read(uint32_t rn)
                    240: {
                    241:     return mmu_read(env, rn);
                    242: }
                    243: 
                    244: void helper_mmu_write(uint32_t rn, uint32_t v)
                    245: {
                    246:     mmu_write(env, rn, v);
                    247: }
1.1.1.2   root      248: 
                    249: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
                    250:                           int is_asi, int size)
                    251: {
                    252:     CPUState *saved_env;
1.1.1.3 ! root      253: 
        !           254:     if (!cpu_single_env) {
        !           255:         /* XXX: ???   */
        !           256:         return;
        !           257:     }
        !           258: 
1.1.1.2   root      259:     /* XXX: hack to restore env in all cases, even if not called from
                    260:        generated code */
                    261:     saved_env = env;
                    262:     env = cpu_single_env;
                    263:     qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
                    264:              addr, is_write, is_exec);
                    265:     if (!(env->sregs[SR_MSR] & MSR_EE)) {
                    266:         env = saved_env;
                    267:         return;
                    268:     }
                    269: 
                    270:     env->sregs[SR_EAR] = addr;
                    271:     if (is_exec) {
                    272:         if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
                    273:             env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
                    274:             helper_raise_exception(EXCP_HW_EXCP);
                    275:         }
                    276:     } else {
                    277:         if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
                    278:             env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
                    279:             helper_raise_exception(EXCP_HW_EXCP);
                    280:         }
                    281:     }
                    282:     env = saved_env;
                    283: }
1.1.1.3 ! root      284: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.