Annotation of qemu/target-cris/helper.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  *  CRIS helper routines.
                      3:  *
                      4:  *  Copyright (c) 2007 AXIS Communications AB
                      5:  *  Written by Edgar E. Iglesias.
                      6:  *
                      7:  * This library is free software; you can redistribute it and/or
                      8:  * modify it under the terms of the GNU Lesser General Public
                      9:  * License as published by the Free Software Foundation; either
                     10:  * version 2 of the License, or (at your option) any later version.
                     11:  *
                     12:  * This library is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * Lesser General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU Lesser General Public
1.1.1.3   root       18:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       19:  */
                     20: 
                     21: #include <stdio.h>
                     22: #include <string.h>
                     23: 
                     24: #include "config.h"
                     25: #include "cpu.h"
                     26: #include "mmu.h"
                     27: #include "host-utils.h"
                     28: 
1.1.1.2   root       29: 
                     30: //#define CRIS_HELPER_DEBUG
                     31: 
                     32: 
                     33: #ifdef CRIS_HELPER_DEBUG
                     34: #define D(x) x
                     35: #define D_LOG(...) qemu_log(__VA__ARGS__)
                     36: #else
                     37: #define D(x)
                     38: #define D_LOG(...) do { } while (0)
                     39: #endif
                     40: 
1.1       root       41: #if defined(CONFIG_USER_ONLY)
                     42: 
                     43: void do_interrupt (CPUState *env)
                     44: {
1.1.1.2   root       45:        env->exception_index = -1;
                     46:        env->pregs[PR_ERP] = env->pc;
1.1       root       47: }
                     48: 
                     49: int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
1.1.1.8 ! root       50:                               int mmu_idx)
1.1       root       51: {
1.1.1.2   root       52:        env->exception_index = 0xaa;
                     53:        env->pregs[PR_EDA] = address;
                     54:        cpu_dump_state(env, stderr, fprintf, 0);
                     55:        return 1;
1.1       root       56: }
                     57: 
                     58: #else /* !CONFIG_USER_ONLY */
                     59: 
1.1.1.2   root       60: 
                     61: static void cris_shift_ccs(CPUState *env)
                     62: {
                     63:        uint32_t ccs;
                     64:        /* Apply the ccs shift.  */
                     65:        ccs = env->pregs[PR_CCS];
                     66:        ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
                     67:        env->pregs[PR_CCS] = ccs;
                     68: }
                     69: 
1.1       root       70: int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1.1.1.8 ! root       71:                                int mmu_idx)
1.1       root       72: {
1.1.1.3   root       73:        struct cris_mmu_result res;
1.1       root       74:        int prot, miss;
1.1.1.2   root       75:        int r = -1;
1.1       root       76:        target_ulong phy;
                     77: 
1.1.1.2   root       78:        D(printf ("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
1.1.1.4   root       79:        miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
1.1.1.5   root       80:                                  rw, mmu_idx, 0);
1.1       root       81:        if (miss)
                     82:        {
1.1.1.2   root       83:                if (env->exception_index == EXCP_BUSFAULT)
1.1.1.5   root       84:                        cpu_abort(env,
1.1.1.2   root       85:                                  "CRIS: Illegal recursive bus fault."
1.1.1.5   root       86:                                 "addr=%x rw=%d\n",
                     87:                                 address, rw);
1.1.1.2   root       88: 
1.1.1.4   root       89:                env->pregs[PR_EDA] = address;
1.1.1.2   root       90:                env->exception_index = EXCP_BUSFAULT;
                     91:                env->fault_vector = res.bf_vec;
                     92:                r = 1;
1.1       root       93:        }
                     94:        else
                     95:        {
1.1.1.2   root       96:                /*
                     97:                 * Mask off the cache selection bit. The ETRAX busses do not
                     98:                 * see the top bit.
                     99:                 */
                    100:                phy = res.phy & ~0x80000000;
                    101:                prot = res.prot;
1.1.1.5   root      102:                tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
1.1.1.6   root      103:                              prot, mmu_idx, TARGET_PAGE_SIZE);
1.1.1.5   root      104:                 r = 0;
1.1       root      105:        }
1.1.1.2   root      106:        if (r > 0)
1.1.1.8 ! root      107:             D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
        !           108:                   __func__, r, env->interrupt_request, address, res.phy,
        !           109:                   res.bf_vec, env->pc);
1.1.1.2   root      110:        return r;
1.1       root      111: }
                    112: 
1.1.1.5   root      113: static void do_interruptv10(CPUState *env)
                    114: {
                    115:        int ex_vec = -1;
                    116: 
                    117:        D_LOG( "exception index=%d interrupt_req=%d\n",
                    118:                   env->exception_index,
                    119:                   env->interrupt_request);
                    120: 
                    121:        assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
                    122:        switch (env->exception_index)
                    123:        {
                    124:                case EXCP_BREAK:
                    125:                        /* These exceptions are genereated by the core itself.
                    126:                           ERP should point to the insn following the brk.  */
                    127:                        ex_vec = env->trap_vector;
                    128:                        env->pregs[PR_ERP] = env->pc;
                    129:                        break;
                    130: 
                    131:                case EXCP_NMI:
                    132:                        /* NMI is hardwired to vector zero.  */
                    133:                        ex_vec = 0;
                    134:                        env->pregs[PR_CCS] &= ~M_FLAG;
                    135:                        env->pregs[PR_NRP] = env->pc;
                    136:                        break;
                    137: 
                    138:                case EXCP_BUSFAULT:
                    139:                         cpu_abort(env, "Unhandled busfault");
                    140:                        break;
                    141: 
                    142:                default:
                    143:                        /* The interrupt controller gives us the vector.  */
                    144:                        ex_vec = env->interrupt_vector;
                    145:                        /* Normal interrupts are taken between
                    146:                           TB's.  env->pc is valid here.  */
                    147:                        env->pregs[PR_ERP] = env->pc;
                    148:                        break;
                    149:        }
                    150: 
                    151:        if (env->pregs[PR_CCS] & U_FLAG) {
                    152:                /* Swap stack pointers.  */
                    153:                env->pregs[PR_USP] = env->regs[R_SP];
                    154:                env->regs[R_SP] = env->ksp;
                    155:        }
                    156: 
                    157:        /* Now that we are in kernel mode, load the handlers address.  */
                    158:        env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
                    159:        env->locked_irq = 1;
1.1.1.8 ! root      160:        env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
1.1.1.5   root      161: 
                    162:        qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
                    163:                      __func__, env->pc, ex_vec, 
                    164:                      env->pregs[PR_CCS],
                    165:                      env->pregs[PR_PID], 
                    166:                      env->pregs[PR_ERP]);
                    167: }
                    168: 
1.1       root      169: void do_interrupt(CPUState *env)
                    170: {
1.1.1.2   root      171:        int ex_vec = -1;
1.1       root      172: 
1.1.1.5   root      173:        if (env->pregs[PR_VR] < 32)
                    174:                return do_interruptv10(env);
                    175: 
1.1.1.2   root      176:        D_LOG( "exception index=%d interrupt_req=%d\n",
                    177:                   env->exception_index,
                    178:                   env->interrupt_request);
1.1       root      179: 
                    180:        switch (env->exception_index)
                    181:        {
                    182:                case EXCP_BREAK:
1.1.1.2   root      183:                        /* These exceptions are genereated by the core itself.
                    184:                           ERP should point to the insn following the brk.  */
                    185:                        ex_vec = env->trap_vector;
                    186:                        env->pregs[PR_ERP] = env->pc;
                    187:                        break;
1.1       root      188: 
1.1.1.2   root      189:                case EXCP_NMI:
                    190:                        /* NMI is hardwired to vector zero.  */
                    191:                        ex_vec = 0;
                    192:                        env->pregs[PR_CCS] &= ~M_FLAG;
                    193:                        env->pregs[PR_NRP] = env->pc;
1.1       root      194:                        break;
1.1.1.2   root      195: 
                    196:                case EXCP_BUSFAULT:
                    197:                        ex_vec = env->fault_vector;
                    198:                        env->pregs[PR_ERP] = env->pc;
1.1       root      199:                        break;
                    200: 
                    201:                default:
1.1.1.2   root      202:                        /* The interrupt controller gives us the vector.  */
                    203:                        ex_vec = env->interrupt_vector;
                    204:                        /* Normal interrupts are taken between
                    205:                           TB's.  env->pc is valid here.  */
                    206:                        env->pregs[PR_ERP] = env->pc;
                    207:                        break;
                    208:        }
1.1       root      209: 
1.1.1.2   root      210:        /* Fill in the IDX field.  */
                    211:        env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
                    212: 
                    213:        if (env->dslot) {
                    214:                D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
                    215:                          " ERP=%x pid=%x ccs=%x cc=%d %x\n",
                    216:                          ex_vec, env->pc, env->dslot,
                    217:                          env->regs[R_SP],
                    218:                          env->pregs[PR_ERP], env->pregs[PR_PID],
                    219:                          env->pregs[PR_CCS],
                    220:                          env->cc_op, env->cc_mask);
                    221:                /* We loose the btarget, btaken state here so rexec the
                    222:                   branch.  */
                    223:                env->pregs[PR_ERP] -= env->dslot;
                    224:                /* Exception starts with dslot cleared.  */
                    225:                env->dslot = 0;
                    226:        }
                    227:        
                    228:        if (env->pregs[PR_CCS] & U_FLAG) {
                    229:                /* Swap stack pointers.  */
                    230:                env->pregs[PR_USP] = env->regs[R_SP];
                    231:                env->regs[R_SP] = env->ksp;
1.1       root      232:        }
1.1.1.2   root      233: 
                    234:        /* Apply the CRIS CCS shift. Clears U if set.  */
                    235:        cris_shift_ccs(env);
1.1.1.4   root      236: 
1.1.1.6   root      237:        /* Now that we are in kernel mode, load the handlers address.
                    238:           This load may not fault, real hw leaves that behaviour as
                    239:           undefined.  */
1.1.1.4   root      240:        env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
                    241: 
1.1.1.6   root      242:        /* Clear the excption_index to avoid spurios hw_aborts for recursive
                    243:           bus faults.  */
                    244:        env->exception_index = -1;
                    245: 
1.1.1.5   root      246:        D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
                    247:                   __func__, env->pc, ex_vec,
1.1.1.2   root      248:                   env->pregs[PR_CCS],
                    249:                   env->pregs[PR_PID], 
                    250:                   env->pregs[PR_ERP]);
1.1       root      251: }
                    252: 
                    253: target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
                    254: {
                    255:        uint32_t phy = addr;
1.1.1.3   root      256:        struct cris_mmu_result res;
1.1       root      257:        int miss;
1.1.1.5   root      258: 
                    259:        miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
                    260:        /* If D TLB misses, try I TLB.  */
                    261:        if (miss) {
                    262:                miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
                    263:        }
                    264: 
1.1       root      265:        if (!miss)
                    266:                phy = res.phy;
1.1.1.2   root      267:        D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
1.1       root      268:        return phy;
                    269: }
                    270: #endif

unix.superglobalmegacorp.com