gonzui


Format: Advanced Search

tkernel_2/monitor/cmdsvc/src/armv6/register.cbare sourcepermlink (0.06 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by T-Engine Forum at 2013/03/04.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: /*
   17:  *      register.c
   18:  *
   19:  *       Register-related operations (after ARMV6)
   20:  */
   21: 
   22: #include "../cmdsvc.h"
   23: #include <sys/sysinfo.h>
   24: 
   25: EXPORT  UW       regStack[39 + 10 + 2];
   26: 
   27: /*
   28:         register definition table
   29: 
   30:         * registers are saved to regStack on entry to the monitor.
   31:            The value in register ID follows the order saved in register stack (below).
   32:            (See eitent.S)
   33: 
   34:         regStack[0-7]          r0 .. r7
   35:                 [8,9]         Entry cspr, ip
   36:                 [10]          return cspr
   37:                 [11]          return r15(pc)
   38:                 [12-18]          USR:       r8 ..r12, sp, lr
   39:                 [19-26]          FIQ:       spsr, r8 ..r12, sp, lr
   40:                 [27-29]          IRQ:       spsr, sp, lr
   41:                 [30-32]          ABT:       spsr, sp, lr
   42:                 [33-35]          UND:       spsr, sp, lr
   43:                 [36-38]          SVC:       spsr, sp, lr
   44: 
   45:                 [39]       CP15: SCTLR             (CP15.c1.0.c0.0)
   46:                 [40-42]          TTBR0,TTBR1,TTBCR (CP15.c2.0.c0.0 - 2)
   47:                 [43]             DACR              (CP15.c3.0.c0.0)
   48:                 [44-45]          DFSR,IFSR         (CP15.c5.0.c0.0 - 1)
   49:                 [46-47]          DFAR,IFAR         (CP15.c6.0.c0.0,2)
   50:                 [48]             CTXIDR            (CP15.c13.0.c0.1)
   51: */
   52: 
   53: #define L_REGNM         8
   54: typedef struct {
   55:         UB     name[L_REGNM];              // register name
   56:         UW     id;                 // register ID
   57: } REGTAB;
   58: 
   59: #define R_GEN           0x001000 // general register
   60: #define R_CTL           0x002000 // control register
   61: #define R_GRP           0x010000 // register group
   62: 
   63: #define R_LF            0x080000  // forced linefeed
   64: #define R_GAP           0x040000 // empty line
   65: 
   66: #define R_ONLY          0x100           // disable setup
   67: #define SPEC(n)         (0x200 | (n))  // special
   68: 
   69: #define ixCPSR          10              // CPSR index
   70: #define ixPC            11                // PC index
   71: 
   72: #define ixUSR           12
   73: #define ixFIQ           (19 + 1) // FIQ: SPSR,R8-R14
   74: #define ixIRQ           (27 - 4) // IRQ: SPSR,R13,R14
   75: #define ixABT           (30 - 4) // ABT: SPSR,R13,R14
   76: #define ixUND           (33 - 4) // UND: SPSR,R13,R14
   77: #define ixSVC           (36 - 4) // SVC: SPSR,R13,R14
   78: #define ixSP_SVC        (ixSVC + 5)    // SVC SP index
   79: 
   80: #define ixCP15          39              // CP15 index
   81: #define ixCP15R1        (ixCP15 + 0)
   82: 
   83: #define N_ACTREGS       (16 + 7 + 7 + 8 + 7 + 10)
   84: #define N_REGS          (N_ACTREGS + 3)
   85: 
   86: LOCAL   const     REGTAB      regTab[N_REGS] = {
   87:         {"R0      ",   R_GEN + 0x00                      }, // 0
   88:         {"R1      ",   R_GEN + 0x01                      }, // 1
   89:         {"R2      ",   R_GEN + 0x02                      }, // 2
   90:         {"R3      ",   R_GEN + 0x03 + R_LF               },   // 3
   91:         {"R4      ",   R_GEN + 0x04                      }, // 4
   92:         {"R5      ",   R_GEN + 0x05                      }, // 5
   93:         {"R6      ",   R_GEN + 0x06                      }, // 6
   94:         {"R7      ",   R_GEN + 0x07 + R_LF               },   // 7
   95:         {"R8      ",   R_GEN + SPEC(0x00)                },    // 8
   96:         {"R9      ",   R_GEN + SPEC(0x01)                },    // 9
   97:         {"R10/SL  ",   R_GEN + SPEC(0x02)                },    // 10
   98:         {"R11/FP  ",   R_GEN + SPEC(0x03) + R_LF },      // 11
   99:         {"R12/IP  ",   R_GEN + SPEC(0x04)                },    // 12
  100:         {"R13/SP  ",   R_GEN + SPEC(0x05)                },    // 13
  101:         {"R14/LR  ",   R_GEN + SPEC(0x06)                },    // 14
  102:         {"R15/PC  ",   R_GEN + ixPC + R_LF               },   // 15
  103: 
  104:         {"R8_USR  ",   R_GEN + ixUSR + 0 + R_GAP },      // 16
  105:         {"R9_USR  ",   R_GEN + ixUSR + 1         },     // 17
  106:         {"R10_USR ",   R_GEN + ixUSR + 2         },     // 18
  107:         {"R11_USR ",   R_GEN + ixUSR + 3 + R_LF  },       // 19
  108:         {"R12_USR ",   R_GEN + ixUSR + 4         },     // 20
  109:         {"R13_USR ",   R_GEN + ixUSR + 5         },     // 21
  110:         {"R14_USR ",   R_GEN + ixUSR + 6 + R_LF  },       // 22
  111: 
  112:         {"R8_FIQ  ",   R_GEN + ixFIQ + 0         },     // 23
  113:         {"R9_FIQ  ",   R_GEN + ixFIQ + 1         },     // 24
  114:         {"R10_FIQ ",   R_GEN + ixFIQ + 2         },     // 25
  115:         {"R11_FIQ ",   R_GEN + ixFIQ + 3 + R_LF  },       // 26
  116:         {"R12_FIQ ",   R_GEN + ixFIQ + 4         },     // 27
  117:         {"R13_FIQ ",   R_GEN + ixFIQ + 5         },     // 28
  118:         {"R14_FIQ ",   R_GEN + ixFIQ + 6 + R_LF  },       // 29
  119: 
  120:         {"R13_IRQ ",   R_GEN + ixIRQ + 5         },     // 30
  121:         {"R14_IRQ ",   R_GEN + ixIRQ + 6         },     // 31
  122:         {"R13_SVC ",   R_GEN + ixSVC + 5         },     // 32
  123:         {"R14_SVC ",   R_GEN + ixSVC + 6 + R_LF  },       // 33
  124:         {"R13_ABT ",   R_GEN + ixABT + 5         },     // 34
  125:         {"R14_ABT ",   R_GEN + ixABT + 6         },     // 35
  126:         {"R13_UND ",   R_GEN + ixUND + 5         },     // 36
  127:         {"R14_UND ",   R_GEN + ixUND + 6 + R_LF  },       // 37
  128: 
  129:         {"CPSR    ",   R_CTL + ixCPSR + R_GAP            },        // 38
  130:         {"SPSR    ",   R_CTL + SPEC(0x08)                },    // 39
  131:         {"SPSR_FIQ",   R_CTL + ixFIQ - 1         },     // 40
  132:         {"SPSR_IRQ",   R_CTL + ixIRQ + 4 + R_LF  },       // 41
  133:         {"SPSR_SVC",   R_CTL + ixSVC + 4         },     // 42
  134:         {"SPSR_ABT",   R_CTL + ixABT + 4         },     // 43
  135:         {"SPSR_UND",   R_CTL + ixUND + 4 + R_LF  },       // 44
  136: 
  137:         {"SCTLR   ",   R_CTL + SPEC(0x0F) +  0 + R_GAP   },        // 45
  138:         {"TTBR0   ",   R_CTL + ixCP15 +  1 + R_ONLY      },   // 46
  139:         {"TTBR1   ",   R_CTL + ixCP15 +  2 + R_ONLY      },   // 47
  140:         {"TTBCR   ",   R_CTL + ixCP15 +  3 + R_ONLY + R_LF},     // 48
  141:         {"DACR    ",   R_CTL + ixCP15 +  4               },   // 49
  142:         {"DFSR    ",   R_CTL + ixCP15 +  5               },   // 50
  143:         {"IFSR    ",   R_CTL + ixCP15 +  6               },   // 51
  144:         {"DFAR    ",   R_CTL + ixCP15 +  7 + R_LF        },     // 52
  145:         {"IFAR    ",   R_CTL + ixCP15 +  8               },   // 53
  146:         {"CTXIDR  ",   R_CTL + ixCP15 +  9 + R_LF        },     // 54
  147: 
  148:         {"G       ",   R_GRP|R_GEN                       },
  149:         {"C       ",   R_GRP|R_CTL                       },
  150:         {"A       ",   R_GRP|R_GEN|R_CTL         },
  151: };
  152: /*
  153:         Searching register name
  154: */
  155: EXPORT  W        searchRegister(UB *name, W grp)
  156: {
  157:         W      i, n, a;
  158:         UB     bf[L_REGNM];
  159:         REGTAB *p;
  160: 
  161:         if (name[L_REGNM] != ' ') return -1;
  162: 
  163:         for (p = (REGTAB*)regTab, i = 0; i < N_REGS; p++, i++) {
  164:                 for (n = 0; n < L_REGNM; n++) if (p->name[n] == '/') break;
  165:                 if (n == L_REGNM) {   // no separator '/' -> a single register name
  166:                         if (memcmp(name, p->name, L_REGNM)) continue;
  167:                 } else {              // has alias
  168:                         // check the name(s) after the separator
  169:                         memset(bf, ' ', sizeof(bf));
  170:                         memcpy(bf, p->name + (n + 1), L_REGNM - (n + 1));
  171:                         a = memcmp(name, bf, L_REGNM - n);
  172: 
  173:                         // check the name before the separator
  174:                         memset(bf, ' ', sizeof(bf));
  175:                         memcpy(bf, p->name, n);
  176:                         if (a && memcmp(name, bf, n + 1)) continue;
  177:                 }
  178:                 if (grp == 0 && (p->id & R_GRP)) break;
  179:                 return i;
  180:         }
  181:         return -1;
  182: }
  183: /*
  184:         obtain CPU mode index
  185: */
  186: LOCAL   W ixCpuMode(void)
  187: {
  188:         // obtain mode
  189:         switch(regStack[ixCPSR] & PSR_M(31)) {
  190:         case PSR_USR:
  191:         case PSR_SYS:  return ixUSR;
  192:         case PSR_FIQ:  return ixFIQ;
  193:         case PSR_IRQ:  return ixIRQ;
  194:         case PSR_SVC:  return ixSVC;
  195:         case PSR_ABT:  return ixABT;
  196:         case PSR_UND:  return ixUND;
  197:         }
  198:         return 0;
  199: }
  200: /*
  201:         obtain register value
  202: */
  203: EXPORT  UW       getRegister(W regno)
  204: {
  205:         W      i, ix;
  206: 
  207:         i = regTab[regno].id & (R_GRP | 0x3ff);
  208: 
  209:         // normal register
  210:         if (i < SPEC(0)) return regStack[i & 0xff];
  211: 
  212:         // obtain mode
  213:         ix = ixCpuMode();
  214: 
  215:         // special register
  216:         switch(i) {
  217:         case SPEC(0x00):       // R8
  218:         case SPEC(0x01):       // R9
  219:         case SPEC(0x02):       // R10
  220:         case SPEC(0x03):       // R11
  221:         case SPEC(0x04):       // R12
  222:                 if (ix != ixFIQ) ix = ixUSR;
  223:         case SPEC(0x05):       // R13
  224:         case SPEC(0x06):       // R14
  225:                 return regStack[ix + i - SPEC(0)];
  226:         case SPEC(0x08):       // SPSR
  227:                 if (ix == ixUSR) return 0;    // undefined
  228:                 if (ix == ixFIQ) ix -= 5;
  229:                 return regStack[ix + 4];
  230:         case SPEC(0x0F):       // CP15 R1
  231:                 return regStack[ixCP15R1];
  232:         }
  233:         // retur 0 on error
  234:         return 0;
  235: }
  236: /*
  237:         Set register value
  238: */
  239: EXPORT  ER       setRegister(W regno, UW val)
  240: {
  241:         W      i, ix;
  242: 
  243:         i = regTab[regno].id & (R_GRP | 0x3ff);
  244:         if (i & R_ONLY) return E_RONLY;                // cannot be set
  245: 
  246:         if (i < SPEC(0)) {     // normal register
  247:                 regStack[i & 0xff] = val;
  248:                 return 0;
  249:         }
  250: 
  251:         // obtain mode
  252:         ix = ixCpuMode();
  253: 
  254:         // special register
  255:         switch(i) {
  256:         case SPEC(0x00):       // R8
  257:         case SPEC(0x01):       // R9
  258:         case SPEC(0x02):       // R10
  259:         case SPEC(0x03):       // R11
  260:         case SPEC(0x04):       // R12
  261:                 if (ix != ixFIQ) ix = ixUSR;
  262:         case SPEC(0x05):       // R13
  263:         case SPEC(0x06):       // R14
  264:                 regStack[ix + i - SPEC(0x00)] = val;
  265:                 break;
  266:         case SPEC(0x08):       // SPSR
  267:                 if (ix == ixUSR) break;       // undefined
  268:                 if (ix == ixFIQ) ix -= 5;
  269:                 regStack[ix + 4] = val;
  270:                 break;
  271:         case SPEC(0x0F):       // CP15 R1
  272:                 regStack[ixCP15R1] &= MASK_CACHEMMU;
  273:                 regStack[ixCP15R1] |= val & VALID_CACHEMMU;
  274:                 break;
  275:         default:
  276:                 return E_PAR;
  277:         }
  278:         return 0;
  279: }
  280: /*
  281:         List the values of register (group)
  282:                 regno < 0 : default group (not specified)
  283: */
  284: EXPORT  void     dispRegister(W regno)
  285: {
  286:         W      i, j, n, id, rid;
  287: 
  288:         if (regno >= N_REGS) return;
  289: 
  290:         id = (regno < 0) ? (R_GRP | R_GEN) : regTab[regno].id;
  291: 
  292:         for (n = i = 0; i < N_ACTREGS; i++) {
  293:                 rid = regTab[i].id;
  294:                 if (!(i == regno || ((id & R_GRP) && (rid & id)))) continue;
  295:                 if (n != 0 && (rid & R_GAP)) DSP_LF;
  296:                 if (n++ & 0x0f) DSP_S("  ");
  297:                 for (j = 0; j < L_REGNM; j++) DSP_CH(regTab[i].name[j]);
  298:                 DSP_F2(S,": ", 08X,getRegister(i));
  299:                 if (rid & R_LF) {DSP_LF; n = 0x10;}
  300:                 if ((id & R_GRP) == 0) break;
  301:         }
  302:         if (n & 0x0f) DSP_LF;
  303: }
  304: /*
  305:         obtain CPSR register value
  306: */
  307: EXPORT  UW       getCurCPSR(void)
  308: {
  309:         return regStack[ixCPSR];
  310: }
  311: /*
  312:         obtain SPSR register value
  313: */
  314: EXPORT  UW       getCurSPSR(void)
  315: {
  316:         return getRegister(39);
  317: }
  318: /*
  319:         obtain PC register value
  320: */
  321: EXPORT  UW       getCurPC(void)
  322: {
  323:         // set LSB = 1 for Thumb mode.
  324:         return regStack[ixPC] | ((regStack[ixCPSR] & PSR_T) ? 1 : 0);
  325: }
  326: EXPORT  UW       getCurPCX(void)
  327: {
  328:         return regStack[ixPC];
  329: }
  330: EXPORT  UW       getCP15(W reg, W opcd)
  331: {
  332:         W      i, d;
  333:         LOCAL  const UH reg_op[] = {
  334:                 0x1000, 0x2000, 0x2001, 0x2002, 0x3000, 0x5000, 0x5001, 0x6000,
  335:                 0x6002, 0xd001,
  336:         };
  337: 
  338:         d = ((reg & 0x0f) << 12) | (opcd & 0x0fff);
  339: 
  340:         for (i = 0; i < sizeof(reg_op) / sizeof(UH); i++) {
  341:                 if (reg_op[i] == d) return regStack[ixCP15 + i];
  342:         }
  343:         return 0;
  344: }
  345: /*
  346:         Set PC register value
  347: */
  348: EXPORT  void     setCurPC(UW val)
  349: {
  350:         if (regStack[ixPC] != val) {
  351:                 // Thumb Bit is changed according to the LSB value of PC.
  352:                 if (val & 0x3)        regStack[ixCPSR] |= PSR_T;
  353:                 else          regStack[ixCPSR] &= ~PSR_T;
  354:                 regStack[ixPC] = val & ~0x1;
  355:         }
  356: }
  357: EXPORT  void     setCurPCX(UW val)
  358: {
  359:         // Thumb Bit is not changed.
  360:         regStack[ixPC] = val & ~0x1;
  361: }
  362: /*
  363:         Set registers for BOOT
  364: */
  365: EXPORT  void     setUpBoot( void *start, BootInfo *bootinfo )
  366: {
  367:         bootFlag = 1; /* suppress the setting register R0 upon exit of the monitor */
  368: 
  369:         regStack[ixCPSR]   = PSR_I | PSR_F | PSR_SVC;
  370:         regStack[0]        = (UW)bootinfo;             // R0 boot parameter
  371:         regStack[ixPC]     = (UW)start;                        // PC start address
  372:         regStack[ixSP_SVC] = (UW)&__stack_bottom;      // SP monitor stack
  373: 
  374:         // MMU enabled, Cache / Write Buffer not enabled
  375:         regStack[ixCP15R1] &= MASK_CACHEMMU;
  376:         regStack[ixCP15R1] |= ENB_MMUONLY;
  377: 
  378:         // system initialization processing
  379:         resetSystem(1);
  380: }
  381: /*
  382:         Check whether we can use KILL command
  383: */
  384: EXPORT  W        isKillValid(void)
  385: {
  386:         // Has TRAP for KILL been define?
  387:         if ( SCArea->intvec[SWI_KILLPROC] == NULL ) return -1;
  388:         return 0;
  389: }
  390: 
  391: #if REF_TKOBJECT
  392: /*
  393:         Check whether T-Kernel/DS functions can be executed?
  394: */
  395: EXPORT  W        isTKDSValid(void)
  396: {
  397:         // Has TRAP for T-Kernel/DS been defined?
  398:         if ( SCArea->intvec[SWI_DEBUG] == NULL ) return -1;
  399:         return 0;
  400: }
  401: 
  402: /*
  403:         Display register of tasks
  404: */
  405: EXPORT W PrintTaskRegister( int (*prfn)( const char *format, ... ),
  406:                                 T_REGS *gr, T_EIT *er, T_CREGS *cr )
  407: {
  408: /*
  409:  *      PC: 12345678             CPSR:12345678 TMF:12345678
  410:  *      R0: 12345678 R1: 12345678 R2: 12345678 R3: 12345678
  411:  *      R4: 12345678 R5: 12345678 R6: 12345678 R7: 12345678
  412:  *      R8: 12345678 R9: 12345678 R10:12345678 R11:12345678
  413:  *      IP: 12345678 LR: 12345678
  414:  *      USP:12345678 SSP:12345678 LSID:1234   UATB:12345678
  415:  */
  416:         (*prfn)("PC: %08x             CPSR:%08x TMF:%08x\n",
  417:                 (UW)er->pc, er->cpsr, er->taskmode);
  418:         (*prfn)("R0: %08x R1: %08x R2: %08x R3: %08x\n",
  419:                 gr->r[0], gr->r[1], gr->r[2], gr->r[3]);
  420:         (*prfn)("R4: %08x R5: %08x R6: %08x R7: %08x\n",
  421:                 gr->r[4], gr->r[5], gr->r[6], gr->r[7]);
  422:         (*prfn)("R8: %08x R9: %08x R10:%08x R11:%08x\n",
  423:                 gr->r[8], gr->r[9], gr->r[10], gr->r[11]);
  424:         (*prfn)("IP: %08x LR: %08x\n",
  425:                 gr->r[12], (UW)gr->lr);
  426:         (*prfn)("USP:%08x SSP:%08x LSID:%-4d   UATB:%08x\n",
  427:                 (UW)cr->usp, (UW)cr->ssp, cr->lsid, (UW)cr->uatb);
  428:         return 6;  /* number of display lines */
  429: }
  430: #endif  /* REF_TKOBJECT */