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

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]);
                     83:     for (i = 0; i < 32; i++) {
                     84:         qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
                     85:         if ((i + 1) % 4 == 0)
                     86:             qemu_log("\n");
                     87:     }
                     88:     qemu_log("\n\n");
                     89: }
                     90: 
                     91: static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin)
                     92: {
                     93:     uint32_t cout = 0;
                     94: 
                     95:     if ((b == ~0) && cin)
                     96:         cout = 1;
                     97:     else if ((~0 - a) < (b + cin))
                     98:         cout = 1;
                     99:     return cout;
                    100: }
                    101: 
                    102: uint32_t helper_cmp(uint32_t a, uint32_t b)
                    103: {
                    104:     uint32_t t;
                    105: 
                    106:     t = b + ~a + 1;
                    107:     if ((b & 0x80000000) ^ (a & 0x80000000))
                    108:         t = (t & 0x7fffffff) | (b & 0x80000000);
                    109:     return t;
                    110: }
                    111: 
                    112: uint32_t helper_cmpu(uint32_t a, uint32_t b)
                    113: {
                    114:     uint32_t t;
                    115: 
                    116:     t = b + ~a + 1;
                    117:     if ((b & 0x80000000) ^ (a & 0x80000000))
                    118:         t = (t & 0x7fffffff) | (a & 0x80000000);
                    119:     return t;
                    120: }
                    121: 
                    122: uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
                    123: {
                    124:     uint32_t d, cf = 0, ncf;
                    125: 
                    126:     if (c)
                    127:         cf = env->sregs[SR_MSR] >> 31;
                    128:     assert(cf == 0 || cf == 1);
                    129:     d = a + b + cf;
                    130: 
                    131:     if (!k) {
                    132:         ncf = compute_carry(a, b, cf);
                    133:         assert(ncf == 0 || ncf == 1);
                    134:         if (ncf)
                    135:             env->sregs[SR_MSR] |= MSR_C | MSR_CC;
                    136:         else
                    137:             env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
                    138:     }
                    139:     D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
                    140:                d, a, b, cf, ncf, k, c));
                    141:     return d;
                    142: }
                    143: 
                    144: uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
                    145: {
                    146:     uint32_t d, cf = 1, ncf;
                    147: 
                    148:     if (c)
                    149:         cf = env->sregs[SR_MSR] >> 31; 
                    150:     assert(cf == 0 || cf == 1);
                    151:     d = b + ~a + cf;
                    152: 
                    153:     if (!k) {
                    154:         ncf = compute_carry(b, ~a, cf);
                    155:         assert(ncf == 0 || ncf == 1);
                    156:         if (ncf)
                    157:             env->sregs[SR_MSR] |= MSR_C | MSR_CC;
                    158:         else
                    159:             env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
                    160:     }
                    161:     D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
                    162:                d, a, b, cf, ncf, k, c));
                    163:     return d;
                    164: }
                    165: 
                    166: static inline int div_prepare(uint32_t a, uint32_t b)
                    167: {
                    168:     if (b == 0) {
                    169:         env->sregs[SR_MSR] |= MSR_DZ;
1.1.1.2 ! root      170: 
        !           171:         if ((env->sregs[SR_MSR] & MSR_EE)
        !           172:             && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) {
        !           173:             env->sregs[SR_ESR] = ESR_EC_DIVZERO;
        !           174:             helper_raise_exception(EXCP_HW_EXCP);
        !           175:         }
1.1       root      176:         return 0;
                    177:     }
                    178:     env->sregs[SR_MSR] &= ~MSR_DZ;
                    179:     return 1;
                    180: }
                    181: 
                    182: uint32_t helper_divs(uint32_t a, uint32_t b)
                    183: {
                    184:     if (!div_prepare(a, b))
                    185:         return 0;
                    186:     return (int32_t)a / (int32_t)b;
                    187: }
                    188: 
                    189: uint32_t helper_divu(uint32_t a, uint32_t b)
                    190: {
                    191:     if (!div_prepare(a, b))
                    192:         return 0;
                    193:     return a / b;
                    194: }
                    195: 
                    196: uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
                    197: {
                    198:     unsigned int i;
                    199:     uint32_t mask = 0xff000000;
                    200: 
                    201:     for (i = 0; i < 4; i++) {
                    202:         if ((a & mask) == (b & mask))
                    203:             return i + 1;
                    204:         mask >>= 8;
                    205:     }
                    206:     return 0;
                    207: }
                    208: 
1.1.1.2 ! root      209: void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
        !           210: {
        !           211:     if (addr & mask) {
        !           212:             qemu_log_mask(CPU_LOG_INT,
        !           213:                           "unaligned access addr=%x mask=%x, wr=%d dr=r%d\n",
        !           214:                           addr, mask, wr, dr);
        !           215:             env->sregs[SR_EAR] = addr;
        !           216:             env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \
        !           217:                                  | (dr & 31) << 5;
        !           218:             if (mask == 3) {
        !           219:                 env->sregs[SR_ESR] |= 1 << 11;
        !           220:             }
        !           221:             if (!(env->sregs[SR_MSR] & MSR_EE)) {
        !           222:                 return;
        !           223:             }
        !           224:             helper_raise_exception(EXCP_HW_EXCP);
        !           225:     }
        !           226: }
        !           227: 
1.1       root      228: #if !defined(CONFIG_USER_ONLY)
                    229: /* Writes/reads to the MMU's special regs end up here.  */
                    230: uint32_t helper_mmu_read(uint32_t rn)
                    231: {
                    232:     return mmu_read(env, rn);
                    233: }
                    234: 
                    235: void helper_mmu_write(uint32_t rn, uint32_t v)
                    236: {
                    237:     mmu_write(env, rn, v);
                    238: }
                    239: #endif
1.1.1.2 ! root      240: 
        !           241: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
        !           242:                           int is_asi, int size)
        !           243: {
        !           244:     CPUState *saved_env;
        !           245:     /* XXX: hack to restore env in all cases, even if not called from
        !           246:        generated code */
        !           247:     saved_env = env;
        !           248:     env = cpu_single_env;
        !           249:     qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
        !           250:              addr, is_write, is_exec);
        !           251:     if (!(env->sregs[SR_MSR] & MSR_EE)) {
        !           252:         env = saved_env;
        !           253:         return;
        !           254:     }
        !           255: 
        !           256:     env->sregs[SR_EAR] = addr;
        !           257:     if (is_exec) {
        !           258:         if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
        !           259:             env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
        !           260:             helper_raise_exception(EXCP_HW_EXCP);
        !           261:         }
        !           262:     } else {
        !           263:         if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
        !           264:             env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
        !           265:             helper_raise_exception(EXCP_HW_EXCP);
        !           266:         }
        !           267:     }
        !           268:     env = saved_env;
        !           269: }

unix.superglobalmegacorp.com

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