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

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

unix.superglobalmegacorp.com

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