home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / sim / arm / armsupp.c < prev    next >
C/C++ Source or Header  |  1995-08-01  |  27KB  |  710 lines

  1. /*  armsupp.c -- ARMulator support code:  ARM6 Instruction Emulator.
  2.     Copyright (C) 1994 Advanced RISC Machines Ltd.
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17.  
  18. #include "armdefs.h"
  19. #include "armemu.h"
  20.  
  21. /***************************************************************************\
  22. *                    Definitions for the support routines                   *
  23. \***************************************************************************/
  24.  
  25. ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg) ;
  26. void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value) ;
  27. ARMword ARMul_GetPC(ARMul_State *state) ;
  28. ARMword ARMul_GetNextPC(ARMul_State *state) ;
  29. void ARMul_SetPC(ARMul_State *state, ARMword value) ;
  30. ARMword ARMul_GetR15(ARMul_State *state) ;
  31. void ARMul_SetR15(ARMul_State *state, ARMword value) ;
  32.  
  33. ARMword ARMul_GetCPSR(ARMul_State *state) ;
  34. void ARMul_SetCPSR(ARMul_State *state, ARMword value) ;
  35. void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs) ;
  36. ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode) ;
  37. void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value) ;
  38. void ARMul_FixSPSR(ARMul_State *state, ARMword instr, ARMword rhs) ;
  39.  
  40. void ARMul_CPSRAltered(ARMul_State *state) ;
  41. void ARMul_R15Altered(ARMul_State *state) ;
  42.  
  43. ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode) ;
  44. static ARMword ModeToBank(ARMul_State *state,ARMword mode) ;
  45.  
  46. unsigned ARMul_NthReg(ARMword instr, unsigned number) ;
  47.  
  48. void ARMul_NegZero(ARMul_State *state, ARMword result) ;
  49. void ARMul_AddCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
  50. void ARMul_AddOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
  51. void ARMul_SubCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
  52. void ARMul_SubOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
  53.  
  54. void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address) ;
  55. void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address) ;
  56. void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source) ;
  57. ARMword ARMul_MRC(ARMul_State *state,ARMword instr) ;
  58. void ARMul_CDP(ARMul_State *state,ARMword instr) ;
  59. void ARMul_UndefInstr(ARMul_State *state,ARMword instr) ;
  60. unsigned IntPending(ARMul_State *state) ;
  61.  
  62. ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data) ;
  63.  
  64. void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay,
  65.                          unsigned (*what)()) ;
  66. void ARMul_EnvokeEvent(ARMul_State *state) ;
  67. unsigned long ARMul_Time(ARMul_State *state) ;
  68. static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to) ;
  69.  
  70. struct EventNode { /* An event list node */
  71.       unsigned (*func)() ; /* The function to call */
  72.       struct EventNode *next ;
  73.       } ;
  74.  
  75. /***************************************************************************\
  76. * This routine returns the value of a register from a mode.                 *
  77. \***************************************************************************/
  78.  
  79. ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg)
  80. {mode &= MODEBITS ;
  81.  if (mode != state->Mode)
  82.     return(state->RegBank[ModeToBank(state,(ARMword)mode)][reg]) ;
  83.  else
  84.     return(state->Reg[reg]) ;
  85. }
  86.  
  87. /***************************************************************************\
  88. * This routine sets the value of a register for a mode.                     *
  89. \***************************************************************************/
  90.  
  91. void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value)
  92. {mode &= MODEBITS ;
  93.  if (mode != state->Mode)
  94.     state->RegBank[ModeToBank(state,(ARMword)mode)][reg] = value ;
  95.  else
  96.     state->Reg[reg] = value ;
  97. }
  98.  
  99. /***************************************************************************\
  100. * This routine returns the value of the PC, mode independently.             *
  101. \***************************************************************************/
  102.  
  103. ARMword ARMul_GetPC(ARMul_State *state)
  104. {if (state->Mode > SVC26MODE)
  105.     return(state->Reg[15]) ;
  106.  else
  107.     return(R15PC) ;
  108. }
  109.  
  110. /***************************************************************************\
  111. * This routine returns the value of the PC, mode independently.             *
  112. \***************************************************************************/
  113.  
  114. ARMword ARMul_GetNextPC(ARMul_State *state)
  115. {if (state->Mode > SVC26MODE)
  116.     return(state->Reg[15] + 4) ;
  117.  else
  118.     return((state->Reg[15] + 4) & R15PCBITS) ;
  119. }
  120.  
  121. /***************************************************************************\
  122. * This routine sets the value of the PC.                                    *
  123. \***************************************************************************/
  124.  
  125. void ARMul_SetPC(ARMul_State *state, ARMword value)
  126. {if (ARMul_MODE32BIT)
  127.     state->Reg[15] = value & PCBITS ;
  128.  else
  129.     state->Reg[15] = R15CCINTMODE | (value & R15PCBITS) ;
  130.  FLUSHPIPE ;
  131. }
  132.  
  133. /***************************************************************************\
  134. * This routine returns the value of register 15, mode independently.        *
  135. \***************************************************************************/
  136.  
  137. ARMword ARMul_GetR15(ARMul_State *state)
  138. {if (state->Mode > SVC26MODE)
  139.     return(state->Reg[15]) ;
  140.  else
  141.     return(R15PC | ECC | ER15INT | EMODE) ;
  142. }
  143.  
  144. /***************************************************************************\
  145. * This routine sets the value of Register 15.                               *
  146. \***************************************************************************/
  147.  
  148. void ARMul_SetR15(ARMul_State *state, ARMword value)
  149. {
  150.  if (ARMul_MODE32BIT)
  151.     state->Reg[15] = value & PCBITS ;
  152.  else {
  153.     state->Reg[15] = value ;
  154.     ARMul_R15Altered(state) ;
  155.     }
  156.  FLUSHPIPE ;
  157. }
  158.  
  159. /***************************************************************************\
  160. * This routine returns the value of the CPSR                                *
  161. \***************************************************************************/
  162.  
  163. ARMword ARMul_GetCPSR(ARMul_State *state)
  164. {
  165.  return(CPSR) ;
  166.  }
  167.  
  168. /***************************************************************************\
  169. * This routine sets the value of the CPSR                                   *
  170. \***************************************************************************/
  171.  
  172. void ARMul_SetCPSR(ARMul_State *state, ARMword value)
  173. {state->Cpsr = CPSR ;
  174.  SETPSR(state->Cpsr,value) ;
  175.  ARMul_CPSRAltered(state) ;
  176.  }
  177.  
  178. /***************************************************************************\
  179. * This routine does all the nasty bits involved in a write to the CPSR,     *
  180. * including updating the register bank, given a MSR instruction.                    *
  181. \***************************************************************************/
  182.  
  183. void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs)
  184. {state->Cpsr = CPSR ;
  185.  if (state->Bank==USERBANK) { /* Only write flags in user mode */
  186.     if (BIT(19)) {
  187.        SETCC(state->Cpsr,rhs) ;
  188.        }
  189.     }
  190.  else { /* Not a user mode */
  191.     if (BITS(16,19)==9) SETPSR(state->Cpsr,rhs) ;
  192.     else if (BIT(16)) SETINTMODE(state->Cpsr,rhs) ;
  193.     else if (BIT(19)) SETCC(state->Cpsr,rhs) ;
  194.     }
  195.  ARMul_CPSRAltered(state) ;
  196.  }
  197.  
  198. /***************************************************************************\
  199. * Get an SPSR from the specified mode                                       *
  200. \***************************************************************************/
  201.  
  202. ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode)
  203. {ARMword bank = ModeToBank(state,mode & MODEBITS) ;
  204.  if (bank == USERBANK || bank == DUMMYBANK)
  205.     return(CPSR) ;
  206.  else
  207.     return(state->Spsr[bank]) ;
  208. }
  209.  
  210. /***************************************************************************\
  211. * This routine does a write to an SPSR                                      *
  212. \***************************************************************************/
  213.  
  214. void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value)
  215. {ARMword bank = ModeToBank(state,mode & MODEBITS) ;
  216.  if (bank != USERBANK && bank !=DUMMYBANK)
  217.     state->Spsr[bank] = value ;
  218. }
  219.  
  220. /***************************************************************************\
  221. * This routine does a write to the current SPSR, given an MSR instruction   *
  222. \***************************************************************************/
  223.  
  224. void ARMul_FixSPSR(ARMul_State *state, ARMword instr, ARMword rhs)
  225. {if (state->Bank != USERBANK && state->Bank !=DUMMYBANK) {
  226.     if (BITS(16,19)==9) SETPSR(state->Spsr[state->Bank],rhs) ;
  227.     else if (BIT(16)) SETINTMODE(state->Spsr[state->Bank],rhs) ;
  228.     else if (BIT(19)) SETCC(state->Spsr[state->Bank],rhs) ;
  229.     }
  230. }
  231.  
  232. /***************************************************************************\
  233. * This routine updates the state of the emulator after the Cpsr has been    *
  234. * changed.  Both the processor flags and register bank are updated.         *
  235. \***************************************************************************/
  236.  
  237. void ARMul_CPSRAltered(ARMul_State *state)
  238. {ARMword oldmode ;
  239.  
  240.  if (state->prog32Sig == LOW)
  241.     state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS) ;
  242.  oldmode = state->Mode ;
  243.  if (state->Mode != (state->Cpsr & MODEBITS)) {
  244.     state->Mode = ARMul_SwitchMode(state,state->Mode,state->Cpsr & MODEBITS) ;
  245.     state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
  246.     }
  247.  
  248.  ASSIGNINT(state->Cpsr & INTBITS) ;
  249.  ASSIGNN((state->Cpsr & NBIT) != 0) ;
  250.  ASSIGNZ((state->Cpsr & ZBIT) != 0) ;
  251.  ASSIGNC((state->Cpsr & CBIT) != 0) ;
  252.  ASSIGNV((state->Cpsr & VBIT) != 0) ;
  253.  
  254.  if (oldmode > SVC26MODE) {
  255.     if (state->Mode <= SVC26MODE) {
  256.        state->Emulate = CHANGEMODE ;
  257.        state->Reg[15] = ECC | ER15INT | EMODE | R15PC ;
  258.        }
  259.     }
  260.  else {
  261.     if (state->Mode > SVC26MODE) {
  262.        state->Emulate = CHANGEMODE ;
  263.        state->Reg[15] = R15PC ;
  264.        }
  265.     else
  266.        state->Reg[15] = ECC | ER15INT | EMODE | R15PC ;
  267.     }
  268.  
  269. }
  270.  
  271. /***************************************************************************\
  272. * This routine updates the state of the emulator after register 15 has      *
  273. * been changed.  Both the processor flags and register bank are updated.    *
  274. * This routine should only be called from a 26 bit mode.                    *
  275. \***************************************************************************/
  276.  
  277. void ARMul_R15Altered(ARMul_State *state)
  278. {
  279.  if (state->Mode != R15MODE) {
  280.     state->Mode = ARMul_SwitchMode(state,state->Mode,R15MODE) ;
  281.     state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
  282.     }
  283.  if (state->Mode > SVC26MODE)
  284.     state->Emulate = CHANGEMODE ;
  285.  ASSIGNR15INT(R15INT) ;
  286.  ASSIGNN((state->Reg[15] & NBIT) != 0) ;
  287.  ASSIGNZ((state->Reg[15] & ZBIT) != 0) ;
  288.  ASSIGNC((state->Reg[15] & CBIT) != 0) ;
  289.  ASSIGNV((state->Reg[15] & VBIT) != 0) ;
  290. }
  291.  
  292. /***************************************************************************\
  293. * This routine controls the saving and restoring of registers across mode   *
  294. * changes.  The regbank matrix is largely unused, only rows 13 and 14 are   *
  295. * used across all modes, 8 to 14 are used for FIQ, all others use the USER  *
  296. * column.  It's easier this way.  old and new parameter are modes numbers.  *
  297. * Notice the side effect of changing the Bank variable.                     *
  298. \***************************************************************************/
  299.  
  300. ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode)
  301. {unsigned i ;
  302.  
  303.  oldmode = ModeToBank(state,oldmode) ;
  304.  state->Bank = ModeToBank(state,newmode) ;
  305.  if (oldmode != state->Bank) { /* really need to do it */
  306.     switch (oldmode) { /* save away the old registers */
  307.        case USERBANK  :
  308.        case IRQBANK   :
  309.        case SVCBANK   :
  310.        case ABORTBANK :
  311.        case UNDEFBANK : if (state->Bank == FIQBANK)
  312.                            for (i = 8 ; i < 13 ; i++)
  313.                               state->RegBank[USERBANK][i] = state->Reg[i] ;
  314.                         state->RegBank[oldmode][13] = state->Reg[13] ;
  315.                         state->RegBank[oldmode][14] = state->Reg[14] ;
  316.                         break ;
  317.        case FIQBANK   : for (i = 8 ; i < 15 ; i++)
  318.                            state->RegBank[FIQBANK][i] = state->Reg[i] ;
  319.                         break ;
  320.        case DUMMYBANK : for (i = 8 ; i < 15 ; i++)
  321.                            state->RegBank[DUMMYBANK][i] = 0 ;
  322.                         break ;
  323.  
  324.        }
  325.     switch (state->Bank) { /* restore the new registers */
  326.        case USERBANK  :
  327.        case IRQBANK   :
  328.        case SVCBANK   :
  329.        case ABORTBANK :
  330.        case UNDEFBANK : if (oldmode == FIQBANK)
  331.                            for (i = 8 ; i < 13 ; i++)
  332.                               state->Reg[i] = state->RegBank[USERBANK][i] ;
  333.                         state->Reg[13] = state->RegBank[state->Bank][13] ;
  334.                         state->Reg[14] = state->RegBank[state->Bank][14] ;
  335.                         break ;
  336.        case FIQBANK  : for (i = 8 ; i < 15 ; i++)
  337.                            state->Reg[i] = state->RegBank[FIQBANK][i] ;
  338.                         break ;
  339.        case DUMMYBANK : for (i = 8 ; i < 15 ; i++)
  340.                            state->Reg[i] = 0 ;
  341.                         break ;
  342.        } /* switch */
  343.     } /* if */
  344.     return(newmode) ;
  345. }
  346.  
  347. /***************************************************************************\
  348. * Given a processor mode, this routine returns the register bank that       *
  349. * will be accessed in that mode.                                            *
  350. \***************************************************************************/
  351.  
  352. static ARMword ModeToBank(ARMul_State *state, ARMword mode)
  353. {static ARMword bankofmode[] = {USERBANK,  FIQBANK,   IRQBANK,   SVCBANK,
  354.                                 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
  355.                                 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
  356.                                 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
  357.                                 USERBANK,  FIQBANK,   IRQBANK,   SVCBANK,
  358.                                 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
  359.                                 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK
  360.                                 } ;
  361.  
  362.  if (mode > UNDEF32MODE)
  363.     return(DUMMYBANK) ;
  364.  else
  365.     return(bankofmode[mode]) ;
  366.  }
  367.  
  368. /***************************************************************************\
  369. * Returns the register number of the nth register in a reg list.            *
  370. \***************************************************************************/
  371.  
  372. unsigned ARMul_NthReg(ARMword instr, unsigned number)
  373. {unsigned bit, upto ;
  374.  
  375.  for (bit = 0, upto = 0 ; upto <= number ; bit++)
  376.     if (BIT(bit)) upto++ ;
  377.  return(bit - 1) ;
  378. }
  379.  
  380. /***************************************************************************\
  381. * Assigns the N and Z flags depending on the value of result                *
  382. \***************************************************************************/
  383.  
  384. void ARMul_NegZero(ARMul_State *state, ARMword result)
  385. {
  386.  if (NEG(result)) { SETN ; CLEARZ ; }
  387.  else if (result == 0) { CLEARN ; SETZ ; }
  388.  else { CLEARN ; CLEARZ ; } ;
  389.  }
  390.  
  391. /***************************************************************************\
  392. * Assigns the C flag after an addition of a and b to give result            *
  393. \***************************************************************************/
  394.  
  395. void ARMul_AddCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
  396. {
  397.  ASSIGNC( (NEG(a) && NEG(b)) ||
  398.           (NEG(a) && POS(result)) ||
  399.           (NEG(b) && POS(result)) ) ;
  400.  }
  401.  
  402. /***************************************************************************\
  403. * Assigns the V flag after an addition of a and b to give result            *
  404. \***************************************************************************/
  405.  
  406. void ARMul_AddOverflow(ARMul_State *state, ARMword a,ARMword b,ARMword result)
  407. {
  408.  ASSIGNV( (NEG(a) && NEG(b) && POS(result)) ||
  409.           (POS(a) && POS(b) && NEG(result)) ) ;
  410.  }
  411.  
  412. /***************************************************************************\
  413. * Assigns the C flag after an subtraction of a and b to give result         *
  414. \***************************************************************************/
  415.  
  416. void ARMul_SubCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
  417. {
  418. ASSIGNC( (NEG(a) && POS(b)) ||
  419.          (NEG(a) && POS(result)) ||
  420.          (POS(b) && POS(result)) ) ;
  421. }
  422.  
  423. /***************************************************************************\
  424. * Assigns the V flag after an subtraction of a and b to give result         *
  425. \***************************************************************************/
  426.  
  427. void ARMul_SubOverflow(ARMul_State *state,ARMword a,ARMword b,ARMword result)
  428. {
  429. ASSIGNV( (NEG(a) && POS(b) && POS(result)) ||
  430.          (POS(a) && NEG(b) && NEG(result)) ) ;
  431. }
  432.  
  433. /***************************************************************************\
  434. * This function does the work of generating the addresses used in an        *
  435. * LDC instruction.  The code here is always post-indexed, it's up to the    *
  436. * caller to get the input address correct and to handle base register       *
  437. * modification. It also handles the Busy-Waiting.                           *
  438. \***************************************************************************/
  439.  
  440. void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address)
  441. {unsigned cpab ;
  442.  ARMword data ;
  443.  
  444.  UNDEF_LSCPCBaseWb ;
  445.  if (ADDREXCEPT(address)) {
  446.     INTERNALABORT(address) ;
  447.     }
  448.  cpab = (state->LDC[CPNum])(state,ARMul_FIRST,instr,0) ;
  449.  while (cpab == ARMul_BUSY) {
  450.     ARMul_Icycles(state,1,0) ;
  451.     if (IntPending(state)) {
  452.        cpab = (state->LDC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
  453.        return ;
  454.        }
  455.     else
  456.        cpab = (state->LDC[CPNum])(state,ARMul_BUSY,instr,0) ;
  457.     }
  458.  if (cpab == ARMul_CANT) {
  459.     CPTAKEABORT ;
  460.     return ;
  461.     }
  462.  cpab = (state->LDC[CPNum])(state,ARMul_TRANSFER,instr,0) ;
  463.  data = ARMul_LoadWordN(state,address) ;
  464.  BUSUSEDINCPCN ;
  465.  if (BIT(21))
  466.     LSBase = state->Base ;
  467.  cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
  468.  while (cpab == ARMul_INC) {
  469.     address += 4 ;
  470.     data = ARMul_LoadWordN(state,address) ;
  471.     cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
  472.     }
  473.  if (state->abortSig || state->Aborted) {
  474.     TAKEABORT ;
  475.     }
  476.  }
  477.  
  478. /***************************************************************************\
  479. * This function does the work of generating the addresses used in an        *
  480. * STC instruction.  The code here is always post-indexed, it's up to the    *
  481. * caller to get the input address correct and to handle base register       *
  482. * modification. It also handles the Busy-Waiting.                           *
  483. \***************************************************************************/
  484.  
  485. void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address)
  486. {unsigned cpab ;
  487.  ARMword data ;
  488.  
  489.  UNDEF_LSCPCBaseWb ;
  490.  if (ADDREXCEPT(address) || VECTORACCESS(address)) {
  491.     INTERNALABORT(address) ;
  492.     }
  493.  cpab = (state->STC[CPNum])(state,ARMul_FIRST,instr,&data) ;
  494.  while (cpab == ARMul_BUSY) {
  495.     ARMul_Icycles(state,1,0) ;
  496.     if (IntPending(state)) {
  497.        cpab = (state->STC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
  498.        return ;
  499.        }
  500.     else
  501.        cpab = (state->STC[CPNum])(state,ARMul_BUSY,instr,&data) ;
  502.     }
  503.  if (cpab == ARMul_CANT) {
  504.     CPTAKEABORT ;
  505.     return ;
  506.     }
  507. #ifndef MODE32
  508.  if (ADDREXCEPT(address) || VECTORACCESS(address)) {
  509.     INTERNALABORT(address) ;
  510.     }
  511. #endif
  512.  BUSUSEDINCPCN ;
  513.  if (BIT(21))
  514.     LSBase = state->Base ;
  515.  cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
  516.  ARMul_StoreWordN(state,address,data) ;
  517.  while (cpab == ARMul_INC) {
  518.     address += 4 ;
  519.     cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
  520.     ARMul_StoreWordN(state,address,data) ;
  521.     }
  522.  if (state->abortSig || state->Aborted) {
  523.     TAKEABORT ;
  524.     }
  525.  }
  526.  
  527. /***************************************************************************\
  528. *        This function does the Busy-Waiting for an MCR instruction.        *
  529. \***************************************************************************/
  530.  
  531. void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source)
  532. {unsigned cpab ;
  533.  
  534.  cpab = (state->MCR[CPNum])(state,ARMul_FIRST,instr,source) ;
  535.  while (cpab == ARMul_BUSY) {
  536.     ARMul_Icycles(state,1,0) ;
  537.     if (IntPending(state)) {
  538.        cpab = (state->MCR[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
  539.        return ;
  540.        }
  541.     else
  542.        cpab = (state->MCR[CPNum])(state,ARMul_BUSY,instr,source) ;
  543.     }
  544.  if (cpab == ARMul_CANT)
  545.     ARMul_Abort(state,ARMul_UndefinedInstrV) ;
  546.  else {
  547.     BUSUSEDINCPCN ;
  548.     ARMul_Ccycles(state,1,0) ;
  549.     }
  550.  }
  551.  
  552. /***************************************************************************\
  553. *        This function does the Busy-Waiting for an MRC instruction.        *
  554. \***************************************************************************/
  555.  
  556. ARMword ARMul_MRC(ARMul_State *state,ARMword instr)
  557. {unsigned cpab ;
  558.  ARMword result = 0 ;
  559.  
  560.  cpab = (state->MRC[CPNum])(state,ARMul_FIRST,instr,&result) ;
  561.  while (cpab == ARMul_BUSY) {
  562.     ARMul_Icycles(state,1,0) ;
  563.     if (IntPending(state)) {
  564.        cpab = (state->MRC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
  565.        return(0) ;
  566.        }
  567.     else
  568.        cpab = (state->MRC[CPNum])(state,ARMul_BUSY,instr,&result) ;
  569.     }
  570.  if (cpab == ARMul_CANT) {
  571.     ARMul_Abort(state,ARMul_UndefinedInstrV) ;
  572.     result = ECC ; /* Parent will destroy the flags otherwise */
  573.     }
  574.  else {
  575.     BUSUSEDINCPCN ;
  576.     ARMul_Ccycles(state,1,0) ;
  577.     ARMul_Icycles(state,1,0) ;
  578.     }
  579.  return(result) ;
  580. }
  581.  
  582. /***************************************************************************\
  583. *        This function does the Busy-Waiting for an CDP instruction.        *
  584. \***************************************************************************/
  585.  
  586. void ARMul_CDP(ARMul_State *state,ARMword instr)
  587. {unsigned cpab ;
  588.  
  589.  cpab = (state->CDP[CPNum])(state,ARMul_FIRST,instr) ;
  590.  while (cpab == ARMul_BUSY) {
  591.     ARMul_Icycles(state,1,0) ;
  592.     if (IntPending(state)) {
  593.        cpab = (state->CDP[CPNum])(state,ARMul_INTERRUPT,instr) ;
  594.        return ;
  595.        }
  596.     else
  597.        cpab = (state->CDP[CPNum])(state,ARMul_BUSY,instr) ;
  598.     }
  599.  if (cpab == ARMul_CANT)
  600.     ARMul_Abort(state,ARMul_UndefinedInstrV) ;
  601.  else
  602.     BUSUSEDN ;
  603. }
  604.  
  605. /***************************************************************************\
  606. *      This function handles Undefined instructions, as CP isntruction      *
  607. \***************************************************************************/
  608.  
  609. void ARMul_UndefInstr(ARMul_State *state,ARMword instr)
  610. {
  611.  ARMul_Abort(state,ARMul_UndefinedInstrV) ;
  612. }
  613.  
  614. /***************************************************************************\
  615. *           Return TRUE if an interrupt is pending, FALSE otherwise.        *
  616. \***************************************************************************/
  617.  
  618. unsigned IntPending(ARMul_State *state)
  619. {
  620.  if (state->Exception) { /* Any exceptions */
  621.     if (state->NresetSig == LOW) {
  622.        ARMul_Abort(state,ARMul_ResetV) ;
  623.        return(TRUE) ;
  624.        }
  625.     else if (!state->NfiqSig && !FFLAG) {
  626.        ARMul_Abort(state,ARMul_FIQV) ;
  627.        return(TRUE) ;
  628.        }
  629.     else if (!state->NirqSig && !IFLAG) {
  630.        ARMul_Abort(state,ARMul_IRQV) ;
  631.        return(TRUE) ;
  632.        }
  633.     }
  634.  return(FALSE) ;
  635.  }
  636.  
  637. /***************************************************************************\
  638. *               Align a word access to a non word boundary                  *
  639. \***************************************************************************/
  640.  
  641. ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data)
  642. {/* this code assumes the address is really unaligned,
  643.     as a shift by 32 is undefined in C */
  644.  
  645.  address = (address & 3) << 3 ; /* get the word address */
  646.  return( ( data >> address) | (data << (32 - address)) ) ; /* rot right */
  647. }
  648.  
  649. /***************************************************************************\
  650. * This routine is used to call another routine after a certain number of    *
  651. * cycles have been executed. The first parameter is the number of cycles    *
  652. * delay before the function is called, the second argument is a pointer     *
  653. * to the function. A delay of zero doesn't work, just call the function.    *
  654. \***************************************************************************/
  655.  
  656. void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, unsigned (*what)())
  657. {unsigned long when ;
  658.  struct EventNode *event ;
  659.  
  660.  if (state->EventSet++ == 0)
  661.     state->Now = ARMul_Time(state) ;
  662.  when = (state->Now + delay) % EVENTLISTSIZE ;
  663.  event = (struct EventNode *)malloc(sizeof(struct EventNode)) ;
  664.  event->func = what ;
  665.  event->next = *(state->EventPtr + when) ;
  666.  *(state->EventPtr + when) = event ;
  667. }
  668.  
  669. /***************************************************************************\
  670. * This routine is called at the beginning of every cycle, to envoke         *
  671. * scheduled events.                                                         *
  672. \***************************************************************************/
  673.  
  674. void ARMul_EnvokeEvent(ARMul_State *state)
  675. {static unsigned long then ;
  676.  
  677.  then = state->Now ;
  678.  state->Now = ARMul_Time(state) % EVENTLISTSIZE ;
  679.  if (then < state->Now) /* schedule events */
  680.     EnvokeList(state,then,state->Now) ;
  681.  else if (then > state->Now) { /* need to wrap around the list */
  682.     EnvokeList(state,then,EVENTLISTSIZE-1L) ;
  683.     EnvokeList(state,0L,state->Now) ;
  684.     }
  685.  }
  686.  
  687. static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to)
  688. /* envokes all the entries in a range */
  689. {struct EventNode *anevent ;
  690.  
  691.  for (; from <= to ; from++) {
  692.     anevent = *(state->EventPtr + from) ;
  693.     while (anevent) {
  694.        (anevent->func)(state) ;
  695.        state->EventSet-- ;
  696.        anevent = anevent->next ;
  697.        }
  698.     *(state->EventPtr + from) = NULL ;
  699.     }
  700.  }
  701.  
  702. /***************************************************************************\
  703. * This routine is returns the number of clock ticks since the last reset.   *
  704. \***************************************************************************/
  705.  
  706. unsigned long ARMul_Time(ARMul_State *state)
  707. {return(state->NumScycles + state->NumNcycles +
  708.         state->NumIcycles + state->NumCcycles + state->NumFcycles) ;
  709. }
  710.