Home | History | Annotate | Line # | Download | only in arm
armsupp.c revision 1.7
      1  1.1  christos /*  armsupp.c -- ARMulator support code:  ARM6 Instruction Emulator.
      2  1.1  christos     Copyright (C) 1994 Advanced RISC Machines Ltd.
      3  1.5  christos 
      4  1.1  christos     This program is free software; you can redistribute it and/or modify
      5  1.1  christos     it under the terms of the GNU General Public License as published by
      6  1.1  christos     the Free Software Foundation; either version 3 of the License, or
      7  1.1  christos     (at your option) any later version.
      8  1.5  christos 
      9  1.1  christos     This program is distributed in the hope that it will be useful,
     10  1.1  christos     but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  christos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  1.1  christos     GNU General Public License for more details.
     13  1.5  christos 
     14  1.1  christos     You should have received a copy of the GNU General Public License
     15  1.1  christos     along with this program; if not, see <http://www.gnu.org/licenses/>. */
     16  1.1  christos 
     17  1.1  christos #include "armdefs.h"
     18  1.1  christos #include "armemu.h"
     19  1.1  christos #include "ansidecl.h"
     20  1.7  christos #include "libiberty.h"
     21  1.5  christos #include <math.h>
     22  1.1  christos 
     23  1.1  christos /* Definitions for the support routines.  */
     24  1.1  christos 
     25  1.1  christos static ARMword ModeToBank (ARMword);
     26  1.1  christos static void    EnvokeList (ARMul_State *, unsigned long, unsigned long);
     27  1.1  christos 
     28  1.1  christos struct EventNode
     29  1.1  christos {					/* An event list node.  */
     30  1.1  christos   unsigned (*func) (ARMul_State *);	/* The function to call.  */
     31  1.1  christos   struct EventNode *next;
     32  1.1  christos };
     33  1.1  christos 
     34  1.1  christos /* This routine returns the value of a register from a mode.  */
     35  1.1  christos 
     36  1.1  christos ARMword
     37  1.1  christos ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
     38  1.1  christos {
     39  1.1  christos   mode &= MODEBITS;
     40  1.1  christos   if (mode != state->Mode)
     41  1.1  christos     return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
     42  1.1  christos   else
     43  1.1  christos     return (state->Reg[reg]);
     44  1.1  christos }
     45  1.1  christos 
     46  1.1  christos /* This routine sets the value of a register for a mode.  */
     47  1.1  christos 
     48  1.1  christos void
     49  1.1  christos ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
     50  1.1  christos {
     51  1.1  christos   mode &= MODEBITS;
     52  1.1  christos   if (mode != state->Mode)
     53  1.1  christos     state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
     54  1.1  christos   else
     55  1.1  christos     state->Reg[reg] = value;
     56  1.1  christos }
     57  1.1  christos 
     58  1.1  christos /* This routine returns the value of the PC, mode independently.  */
     59  1.1  christos 
     60  1.1  christos ARMword
     61  1.1  christos ARMul_GetPC (ARMul_State * state)
     62  1.1  christos {
     63  1.1  christos   if (state->Mode > SVC26MODE)
     64  1.1  christos     return state->Reg[15];
     65  1.1  christos   else
     66  1.1  christos     return R15PC;
     67  1.1  christos }
     68  1.1  christos 
     69  1.1  christos /* This routine returns the value of the PC, mode independently.  */
     70  1.1  christos 
     71  1.1  christos ARMword
     72  1.1  christos ARMul_GetNextPC (ARMul_State * state)
     73  1.1  christos {
     74  1.1  christos   if (state->Mode > SVC26MODE)
     75  1.1  christos     return state->Reg[15] + isize;
     76  1.1  christos   else
     77  1.1  christos     return (state->Reg[15] + isize) & R15PCBITS;
     78  1.1  christos }
     79  1.1  christos 
     80  1.1  christos /* This routine sets the value of the PC.  */
     81  1.1  christos 
     82  1.1  christos void
     83  1.1  christos ARMul_SetPC (ARMul_State * state, ARMword value)
     84  1.1  christos {
     85  1.1  christos   if (ARMul_MODE32BIT)
     86  1.1  christos     state->Reg[15] = value & PCBITS;
     87  1.1  christos   else
     88  1.1  christos     state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
     89  1.1  christos   FLUSHPIPE;
     90  1.1  christos }
     91  1.1  christos 
     92  1.1  christos /* This routine returns the value of register 15, mode independently.  */
     93  1.1  christos 
     94  1.1  christos ARMword
     95  1.1  christos ARMul_GetR15 (ARMul_State * state)
     96  1.1  christos {
     97  1.1  christos   if (state->Mode > SVC26MODE)
     98  1.1  christos     return (state->Reg[15]);
     99  1.1  christos   else
    100  1.1  christos     return (R15PC | ECC | ER15INT | EMODE);
    101  1.1  christos }
    102  1.1  christos 
    103  1.1  christos /* This routine sets the value of Register 15.  */
    104  1.1  christos 
    105  1.1  christos void
    106  1.1  christos ARMul_SetR15 (ARMul_State * state, ARMword value)
    107  1.1  christos {
    108  1.1  christos   if (ARMul_MODE32BIT)
    109  1.1  christos     state->Reg[15] = value & PCBITS;
    110  1.1  christos   else
    111  1.1  christos     {
    112  1.1  christos       state->Reg[15] = value;
    113  1.1  christos       ARMul_R15Altered (state);
    114  1.1  christos     }
    115  1.1  christos   FLUSHPIPE;
    116  1.1  christos }
    117  1.1  christos 
    118  1.1  christos /* This routine returns the value of the CPSR.  */
    119  1.1  christos 
    120  1.1  christos ARMword
    121  1.1  christos ARMul_GetCPSR (ARMul_State * state)
    122  1.1  christos {
    123  1.1  christos   return (CPSR | state->Cpsr);
    124  1.1  christos }
    125  1.1  christos 
    126  1.1  christos /* This routine sets the value of the CPSR.  */
    127  1.1  christos 
    128  1.1  christos void
    129  1.1  christos ARMul_SetCPSR (ARMul_State * state, ARMword value)
    130  1.1  christos {
    131  1.1  christos   state->Cpsr = value;
    132  1.1  christos   ARMul_CPSRAltered (state);
    133  1.1  christos }
    134  1.1  christos 
    135  1.1  christos /* This routine does all the nasty bits involved in a write to the CPSR,
    136  1.1  christos    including updating the register bank, given a MSR instruction.  */
    137  1.1  christos 
    138  1.1  christos void
    139  1.1  christos ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
    140  1.1  christos {
    141  1.1  christos   state->Cpsr = ARMul_GetCPSR (state);
    142  1.1  christos 
    143  1.1  christos   if (state->Mode != USER26MODE
    144  1.1  christos       && state->Mode != USER32MODE)
    145  1.1  christos     {
    146  1.1  christos       /* In user mode, only write flags.  */
    147  1.1  christos       if (BIT (16))
    148  1.1  christos 	SETPSR_C (state->Cpsr, rhs);
    149  1.1  christos       if (BIT (17))
    150  1.1  christos 	SETPSR_X (state->Cpsr, rhs);
    151  1.1  christos       if (BIT (18))
    152  1.1  christos 	SETPSR_S (state->Cpsr, rhs);
    153  1.1  christos     }
    154  1.1  christos   if (BIT (19))
    155  1.1  christos     SETPSR_F (state->Cpsr, rhs);
    156  1.1  christos   ARMul_CPSRAltered (state);
    157  1.1  christos }
    158  1.1  christos 
    159  1.1  christos /* Get an SPSR from the specified mode.  */
    160  1.1  christos 
    161  1.1  christos ARMword
    162  1.1  christos ARMul_GetSPSR (ARMul_State * state, ARMword mode)
    163  1.1  christos {
    164  1.1  christos   ARMword bank = ModeToBank (mode & MODEBITS);
    165  1.1  christos 
    166  1.1  christos   if (! BANK_CAN_ACCESS_SPSR (bank))
    167  1.1  christos     return ARMul_GetCPSR (state);
    168  1.1  christos 
    169  1.1  christos   return state->Spsr[bank];
    170  1.1  christos }
    171  1.1  christos 
    172  1.1  christos /* This routine does a write to an SPSR.  */
    173  1.1  christos 
    174  1.1  christos void
    175  1.1  christos ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
    176  1.1  christos {
    177  1.1  christos   ARMword bank = ModeToBank (mode & MODEBITS);
    178  1.5  christos 
    179  1.1  christos   if (BANK_CAN_ACCESS_SPSR (bank))
    180  1.1  christos     state->Spsr[bank] = value;
    181  1.1  christos }
    182  1.1  christos 
    183  1.1  christos /* This routine does a write to the current SPSR, given an MSR instruction.  */
    184  1.1  christos 
    185  1.1  christos void
    186  1.1  christos ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
    187  1.1  christos {
    188  1.1  christos   if (BANK_CAN_ACCESS_SPSR (state->Bank))
    189  1.1  christos     {
    190  1.1  christos       if (BIT (16))
    191  1.1  christos 	SETPSR_C (state->Spsr[state->Bank], rhs);
    192  1.1  christos       if (BIT (17))
    193  1.1  christos 	SETPSR_X (state->Spsr[state->Bank], rhs);
    194  1.1  christos       if (BIT (18))
    195  1.1  christos 	SETPSR_S (state->Spsr[state->Bank], rhs);
    196  1.1  christos       if (BIT (19))
    197  1.1  christos 	SETPSR_F (state->Spsr[state->Bank], rhs);
    198  1.1  christos     }
    199  1.1  christos }
    200  1.1  christos 
    201  1.1  christos /* This routine updates the state of the emulator after the Cpsr has been
    202  1.1  christos    changed.  Both the processor flags and register bank are updated.  */
    203  1.1  christos 
    204  1.1  christos void
    205  1.1  christos ARMul_CPSRAltered (ARMul_State * state)
    206  1.1  christos {
    207  1.1  christos   ARMword oldmode;
    208  1.1  christos 
    209  1.1  christos   if (state->prog32Sig == LOW)
    210  1.1  christos     state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
    211  1.1  christos 
    212  1.1  christos   oldmode = state->Mode;
    213  1.5  christos 
    214  1.1  christos   if (state->Mode != (state->Cpsr & MODEBITS))
    215  1.1  christos     {
    216  1.1  christos       state->Mode =
    217  1.1  christos 	ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
    218  1.5  christos 
    219  1.1  christos       state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
    220  1.1  christos     }
    221  1.1  christos   state->Cpsr &= ~MODEBITS;
    222  1.1  christos 
    223  1.1  christos   ASSIGNINT (state->Cpsr & INTBITS);
    224  1.1  christos   state->Cpsr &= ~INTBITS;
    225  1.1  christos   ASSIGNN ((state->Cpsr & NBIT) != 0);
    226  1.1  christos   state->Cpsr &= ~NBIT;
    227  1.1  christos   ASSIGNZ ((state->Cpsr & ZBIT) != 0);
    228  1.1  christos   state->Cpsr &= ~ZBIT;
    229  1.1  christos   ASSIGNC ((state->Cpsr & CBIT) != 0);
    230  1.1  christos   state->Cpsr &= ~CBIT;
    231  1.1  christos   ASSIGNV ((state->Cpsr & VBIT) != 0);
    232  1.1  christos   state->Cpsr &= ~VBIT;
    233  1.1  christos   ASSIGNS ((state->Cpsr & SBIT) != 0);
    234  1.1  christos   state->Cpsr &= ~SBIT;
    235  1.1  christos #ifdef MODET
    236  1.1  christos   ASSIGNT ((state->Cpsr & TBIT) != 0);
    237  1.1  christos   state->Cpsr &= ~TBIT;
    238  1.1  christos #endif
    239  1.1  christos 
    240  1.1  christos   if (oldmode > SVC26MODE)
    241  1.1  christos     {
    242  1.1  christos       if (state->Mode <= SVC26MODE)
    243  1.1  christos 	{
    244  1.1  christos 	  state->Emulate = CHANGEMODE;
    245  1.1  christos 	  state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
    246  1.1  christos 	}
    247  1.1  christos     }
    248  1.1  christos   else
    249  1.1  christos     {
    250  1.1  christos       if (state->Mode > SVC26MODE)
    251  1.1  christos 	{
    252  1.1  christos 	  state->Emulate = CHANGEMODE;
    253  1.1  christos 	  state->Reg[15] = R15PC;
    254  1.1  christos 	}
    255  1.1  christos       else
    256  1.1  christos 	state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
    257  1.1  christos     }
    258  1.1  christos }
    259  1.1  christos 
    260  1.1  christos /* This routine updates the state of the emulator after register 15 has
    261  1.1  christos    been changed.  Both the processor flags and register bank are updated.
    262  1.1  christos    This routine should only be called from a 26 bit mode.  */
    263  1.1  christos 
    264  1.1  christos void
    265  1.1  christos ARMul_R15Altered (ARMul_State * state)
    266  1.1  christos {
    267  1.1  christos   if (state->Mode != R15MODE)
    268  1.1  christos     {
    269  1.1  christos       state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
    270  1.1  christos       state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
    271  1.1  christos     }
    272  1.1  christos 
    273  1.1  christos   if (state->Mode > SVC26MODE)
    274  1.1  christos     state->Emulate = CHANGEMODE;
    275  1.1  christos 
    276  1.1  christos   ASSIGNR15INT (R15INT);
    277  1.1  christos 
    278  1.1  christos   ASSIGNN ((state->Reg[15] & NBIT) != 0);
    279  1.1  christos   ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
    280  1.1  christos   ASSIGNC ((state->Reg[15] & CBIT) != 0);
    281  1.1  christos   ASSIGNV ((state->Reg[15] & VBIT) != 0);
    282  1.1  christos }
    283  1.1  christos 
    284  1.1  christos /* This routine controls the saving and restoring of registers across mode
    285  1.1  christos    changes.  The regbank matrix is largely unused, only rows 13 and 14 are
    286  1.1  christos    used across all modes, 8 to 14 are used for FIQ, all others use the USER
    287  1.1  christos    column.  It's easier this way.  old and new parameter are modes numbers.
    288  1.1  christos    Notice the side effect of changing the Bank variable.  */
    289  1.1  christos 
    290  1.1  christos ARMword
    291  1.1  christos ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
    292  1.1  christos {
    293  1.1  christos   unsigned i;
    294  1.1  christos   ARMword  oldbank;
    295  1.1  christos   ARMword  newbank;
    296  1.5  christos 
    297  1.1  christos   oldbank = ModeToBank (oldmode);
    298  1.1  christos   newbank = state->Bank = ModeToBank (newmode);
    299  1.5  christos 
    300  1.1  christos   /* Do we really need to do it?  */
    301  1.1  christos   if (oldbank != newbank)
    302  1.1  christos     {
    303  1.1  christos       /* Save away the old registers.  */
    304  1.1  christos       switch (oldbank)
    305  1.1  christos 	{
    306  1.1  christos 	case USERBANK:
    307  1.1  christos 	case IRQBANK:
    308  1.1  christos 	case SVCBANK:
    309  1.1  christos 	case ABORTBANK:
    310  1.1  christos 	case UNDEFBANK:
    311  1.1  christos 	  if (newbank == FIQBANK)
    312  1.1  christos 	    for (i = 8; i < 13; i++)
    313  1.1  christos 	      state->RegBank[USERBANK][i] = state->Reg[i];
    314  1.1  christos 	  state->RegBank[oldbank][13] = state->Reg[13];
    315  1.1  christos 	  state->RegBank[oldbank][14] = state->Reg[14];
    316  1.1  christos 	  break;
    317  1.1  christos 	case FIQBANK:
    318  1.1  christos 	  for (i = 8; i < 15; i++)
    319  1.1  christos 	    state->RegBank[FIQBANK][i] = state->Reg[i];
    320  1.1  christos 	  break;
    321  1.1  christos 	case DUMMYBANK:
    322  1.1  christos 	  for (i = 8; i < 15; i++)
    323  1.1  christos 	    state->RegBank[DUMMYBANK][i] = 0;
    324  1.1  christos 	  break;
    325  1.1  christos 	default:
    326  1.1  christos 	  abort ();
    327  1.1  christos 	}
    328  1.5  christos 
    329  1.1  christos       /* Restore the new registers.  */
    330  1.1  christos       switch (newbank)
    331  1.1  christos 	{
    332  1.1  christos 	case USERBANK:
    333  1.1  christos 	case IRQBANK:
    334  1.1  christos 	case SVCBANK:
    335  1.1  christos 	case ABORTBANK:
    336  1.1  christos 	case UNDEFBANK:
    337  1.1  christos 	  if (oldbank == FIQBANK)
    338  1.1  christos 	    for (i = 8; i < 13; i++)
    339  1.1  christos 	      state->Reg[i] = state->RegBank[USERBANK][i];
    340  1.1  christos 	  state->Reg[13] = state->RegBank[newbank][13];
    341  1.1  christos 	  state->Reg[14] = state->RegBank[newbank][14];
    342  1.1  christos 	  break;
    343  1.1  christos 	case FIQBANK:
    344  1.1  christos 	  for (i = 8; i < 15; i++)
    345  1.1  christos 	    state->Reg[i] = state->RegBank[FIQBANK][i];
    346  1.1  christos 	  break;
    347  1.1  christos 	case DUMMYBANK:
    348  1.1  christos 	  for (i = 8; i < 15; i++)
    349  1.1  christos 	    state->Reg[i] = 0;
    350  1.1  christos 	  break;
    351  1.1  christos 	default:
    352  1.1  christos 	  abort ();
    353  1.1  christos 	}
    354  1.1  christos     }
    355  1.5  christos 
    356  1.1  christos   return newmode;
    357  1.1  christos }
    358  1.1  christos 
    359  1.1  christos /* Given a processor mode, this routine returns the
    360  1.1  christos    register bank that will be accessed in that mode.  */
    361  1.1  christos 
    362  1.1  christos static ARMword
    363  1.1  christos ModeToBank (ARMword mode)
    364  1.1  christos {
    365  1.1  christos   static ARMword bankofmode[] =
    366  1.1  christos   {
    367  1.1  christos     USERBANK,  FIQBANK,   IRQBANK,   SVCBANK,
    368  1.1  christos     DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
    369  1.1  christos     DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
    370  1.1  christos     DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
    371  1.1  christos     USERBANK,  FIQBANK,   IRQBANK,   SVCBANK,
    372  1.1  christos     DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
    373  1.1  christos     DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
    374  1.1  christos     DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
    375  1.1  christos   };
    376  1.1  christos 
    377  1.7  christos   if (mode >= ARRAY_SIZE (bankofmode))
    378  1.1  christos     return DUMMYBANK;
    379  1.1  christos 
    380  1.1  christos   return bankofmode[mode];
    381  1.1  christos }
    382  1.1  christos 
    383  1.1  christos /* Returns the register number of the nth register in a reg list.  */
    384  1.1  christos 
    385  1.1  christos unsigned
    386  1.1  christos ARMul_NthReg (ARMword instr, unsigned number)
    387  1.1  christos {
    388  1.1  christos   unsigned bit, upto;
    389  1.1  christos 
    390  1.1  christos   for (bit = 0, upto = 0; upto <= number; bit ++)
    391  1.1  christos     if (BIT (bit))
    392  1.1  christos       upto ++;
    393  1.1  christos 
    394  1.1  christos   return (bit - 1);
    395  1.1  christos }
    396  1.1  christos 
    397  1.1  christos /* Assigns the N and Z flags depending on the value of result.  */
    398  1.1  christos 
    399  1.1  christos void
    400  1.1  christos ARMul_NegZero (ARMul_State * state, ARMword result)
    401  1.1  christos {
    402  1.1  christos   if (NEG (result))
    403  1.1  christos     {
    404  1.1  christos       SETN;
    405  1.1  christos       CLEARZ;
    406  1.1  christos     }
    407  1.1  christos   else if (result == 0)
    408  1.1  christos     {
    409  1.1  christos       CLEARN;
    410  1.1  christos       SETZ;
    411  1.1  christos     }
    412  1.1  christos   else
    413  1.1  christos     {
    414  1.1  christos       CLEARN;
    415  1.1  christos       CLEARZ;
    416  1.1  christos     }
    417  1.1  christos }
    418  1.1  christos 
    419  1.1  christos /* Compute whether an addition of A and B, giving RESULT, overflowed.  */
    420  1.1  christos 
    421  1.1  christos int
    422  1.1  christos AddOverflow (ARMword a, ARMword b, ARMword result)
    423  1.1  christos {
    424  1.1  christos   return ((NEG (a) && NEG (b) && POS (result))
    425  1.1  christos 	  || (POS (a) && POS (b) && NEG (result)));
    426  1.1  christos }
    427  1.1  christos 
    428  1.1  christos /* Compute whether a subtraction of A and B, giving RESULT, overflowed.  */
    429  1.1  christos 
    430  1.1  christos int
    431  1.1  christos SubOverflow (ARMword a, ARMword b, ARMword result)
    432  1.1  christos {
    433  1.1  christos   return ((NEG (a) && POS (b) && POS (result))
    434  1.1  christos 	  || (POS (a) && NEG (b) && NEG (result)));
    435  1.1  christos }
    436  1.1  christos 
    437  1.1  christos /* Assigns the C flag after an addition of a and b to give result.  */
    438  1.1  christos 
    439  1.1  christos void
    440  1.1  christos ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
    441  1.1  christos {
    442  1.1  christos   ASSIGNC ((NEG (a) && NEG (b)) ||
    443  1.1  christos 	   (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
    444  1.1  christos }
    445  1.1  christos 
    446  1.1  christos /* Assigns the V flag after an addition of a and b to give result.  */
    447  1.1  christos 
    448  1.1  christos void
    449  1.1  christos ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
    450  1.1  christos {
    451  1.1  christos   ASSIGNV (AddOverflow (a, b, result));
    452  1.1  christos }
    453  1.1  christos 
    454  1.1  christos /* Assigns the C flag after an subtraction of a and b to give result.  */
    455  1.1  christos 
    456  1.1  christos void
    457  1.1  christos ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
    458  1.1  christos {
    459  1.1  christos   ASSIGNC ((NEG (a) && POS (b)) ||
    460  1.1  christos 	   (NEG (a) && POS (result)) || (POS (b) && POS (result)));
    461  1.1  christos }
    462  1.1  christos 
    463  1.1  christos /* Assigns the V flag after an subtraction of a and b to give result.  */
    464  1.1  christos 
    465  1.1  christos void
    466  1.1  christos ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
    467  1.1  christos {
    468  1.1  christos   ASSIGNV (SubOverflow (a, b, result));
    469  1.1  christos }
    470  1.1  christos 
    471  1.5  christos static void
    472  1.5  christos handle_VFP_xfer (ARMul_State * state, ARMword instr)
    473  1.5  christos {
    474  1.5  christos   if (TOPBITS (28) == NV)
    475  1.5  christos     {
    476  1.5  christos       fprintf (stderr, "SIM: UNDEFINED VFP instruction\n");
    477  1.5  christos       return;
    478  1.5  christos     }
    479  1.5  christos 
    480  1.5  christos   if (BITS (25, 27) != 0x6)
    481  1.5  christos     {
    482  1.5  christos       fprintf (stderr, "SIM: ISE: VFP handler called incorrectly\n");
    483  1.5  christos       return;
    484  1.5  christos     }
    485  1.5  christos 
    486  1.5  christos   switch (BITS (20, 24))
    487  1.5  christos     {
    488  1.5  christos     case 0x04:
    489  1.5  christos     case 0x05:
    490  1.5  christos       {
    491  1.5  christos 	/* VMOV double precision to/from two ARM registers.  */
    492  1.5  christos 	int vm  = BITS (0, 3);
    493  1.5  christos 	int rt1 = BITS (12, 15);
    494  1.5  christos 	int rt2 = BITS (16, 19);
    495  1.5  christos 
    496  1.5  christos 	/* FIXME: UNPREDICTABLE if rt1 == 15 or rt2 == 15.  */
    497  1.5  christos 	if (BIT (20))
    498  1.5  christos 	  {
    499  1.5  christos 	    /* Transfer to ARM.  */
    500  1.5  christos 	    /* FIXME: UPPREDICTABLE if rt1 == rt2.  */
    501  1.5  christos 	    state->Reg[rt1] = VFP_dword (vm) & 0xffffffff;
    502  1.5  christos 	    state->Reg[rt2] = VFP_dword (vm) >> 32;
    503  1.5  christos 	  }
    504  1.5  christos 	else
    505  1.5  christos 	  {
    506  1.5  christos 	    VFP_dword (vm) = state->Reg[rt2];
    507  1.5  christos 	    VFP_dword (vm) <<= 32;
    508  1.5  christos 	    VFP_dword (vm) |= (state->Reg[rt1] & 0xffffffff);
    509  1.5  christos 	  }
    510  1.5  christos 	return;
    511  1.5  christos       }
    512  1.5  christos 
    513  1.5  christos     case 0x08:
    514  1.5  christos     case 0x0A:
    515  1.5  christos     case 0x0C:
    516  1.5  christos     case 0x0E:
    517  1.5  christos       {
    518  1.5  christos 	/* VSTM with PUW=011 or PUW=010.  */
    519  1.5  christos 	int n = BITS (16, 19);
    520  1.5  christos 	int imm8 = BITS (0, 7);
    521  1.5  christos 
    522  1.5  christos 	ARMword address = state->Reg[n];
    523  1.5  christos 	if (BIT (21))
    524  1.5  christos 	  state->Reg[n] = address + (imm8 << 2);
    525  1.5  christos 
    526  1.5  christos 	if (BIT (8))
    527  1.5  christos 	  {
    528  1.5  christos 	    int src = (BIT (22) << 4) | BITS (12, 15);
    529  1.5  christos 	    imm8 >>= 1;
    530  1.5  christos 	    while (imm8--)
    531  1.5  christos 	      {
    532  1.5  christos 		if (state->bigendSig)
    533  1.5  christos 		  {
    534  1.5  christos 		    ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
    535  1.5  christos 		    ARMul_StoreWordN (state, address + 4, VFP_dword (src));
    536  1.5  christos 		  }
    537  1.5  christos 		else
    538  1.5  christos 		  {
    539  1.5  christos 		    ARMul_StoreWordN (state, address, VFP_dword (src));
    540  1.5  christos 		    ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
    541  1.5  christos 		  }
    542  1.5  christos 		address += 8;
    543  1.5  christos 		src += 1;
    544  1.5  christos 	      }
    545  1.5  christos 	  }
    546  1.5  christos 	else
    547  1.5  christos 	  {
    548  1.5  christos 	    int src = (BITS (12, 15) << 1) | BIT (22);
    549  1.5  christos 	    while (imm8--)
    550  1.5  christos 	      {
    551  1.5  christos 		ARMul_StoreWordN (state, address, VFP_uword (src));
    552  1.5  christos 		address += 4;
    553  1.5  christos 		src += 1;
    554  1.5  christos 	      }
    555  1.5  christos 	  }
    556  1.5  christos       }
    557  1.5  christos       return;
    558  1.5  christos 
    559  1.5  christos     case 0x10:
    560  1.5  christos     case 0x14:
    561  1.5  christos     case 0x18:
    562  1.5  christos     case 0x1C:
    563  1.5  christos       {
    564  1.5  christos 	/* VSTR */
    565  1.5  christos 	ARMword imm32 = BITS (0, 7) << 2;
    566  1.5  christos 	int base = state->Reg[LHSReg];
    567  1.5  christos 	ARMword address;
    568  1.5  christos 	int dest;
    569  1.5  christos 
    570  1.5  christos 	if (LHSReg == 15)
    571  1.5  christos 	  base = (base + 3) & ~3;
    572  1.5  christos 
    573  1.5  christos 	address = base + (BIT (23) ? imm32 : - imm32);
    574  1.5  christos 
    575  1.5  christos 	if (CPNum == 10)
    576  1.5  christos 	  {
    577  1.5  christos 	    dest = (DESTReg << 1) + BIT (22);
    578  1.5  christos 
    579  1.5  christos 	    ARMul_StoreWordN (state, address, VFP_uword (dest));
    580  1.5  christos 	  }
    581  1.5  christos 	else
    582  1.5  christos 	  {
    583  1.5  christos 	    dest = (BIT (22) << 4) + DESTReg;
    584  1.5  christos 
    585  1.5  christos 	    if (state->bigendSig)
    586  1.5  christos 	      {
    587  1.5  christos 		ARMul_StoreWordN (state, address, VFP_dword (dest) >> 32);
    588  1.5  christos 		ARMul_StoreWordN (state, address + 4, VFP_dword (dest));
    589  1.5  christos 	      }
    590  1.5  christos 	    else
    591  1.5  christos 	      {
    592  1.5  christos 		ARMul_StoreWordN (state, address, VFP_dword (dest));
    593  1.5  christos 		ARMul_StoreWordN (state, address + 4, VFP_dword (dest) >> 32);
    594  1.5  christos 	      }
    595  1.5  christos 	  }
    596  1.5  christos       }
    597  1.5  christos       return;
    598  1.5  christos 
    599  1.5  christos     case 0x12:
    600  1.5  christos     case 0x16:
    601  1.5  christos       if (BITS (16, 19) == 13)
    602  1.5  christos 	{
    603  1.5  christos 	  /* VPUSH */
    604  1.5  christos 	  ARMword address = state->Reg[13] - (BITS (0, 7) << 2);
    605  1.5  christos 	  state->Reg[13] = address;
    606  1.5  christos 
    607  1.5  christos 	  if (BIT (8))
    608  1.5  christos 	    {
    609  1.5  christos 	      int dreg = (BIT (22) << 4) | BITS (12, 15);
    610  1.5  christos 	      int num  = BITS (0, 7) >> 1;
    611  1.5  christos 	      while (num--)
    612  1.5  christos 		{
    613  1.5  christos 		  if (state->bigendSig)
    614  1.5  christos 		    {
    615  1.5  christos 		      ARMul_StoreWordN (state, address, VFP_dword (dreg) >> 32);
    616  1.5  christos 		      ARMul_StoreWordN (state, address + 4, VFP_dword (dreg));
    617  1.5  christos 		    }
    618  1.5  christos 		  else
    619  1.5  christos 		    {
    620  1.5  christos 		      ARMul_StoreWordN (state, address, VFP_dword (dreg));
    621  1.5  christos 		      ARMul_StoreWordN (state, address + 4, VFP_dword (dreg) >> 32);
    622  1.5  christos 		    }
    623  1.5  christos 		  address += 8;
    624  1.5  christos 		  dreg += 1;
    625  1.5  christos 		}
    626  1.5  christos 	    }
    627  1.5  christos 	  else
    628  1.5  christos 	    {
    629  1.5  christos 	      int sreg = (BITS (12, 15) << 1) | BIT (22);
    630  1.5  christos 	      int num  = BITS (0, 7);
    631  1.5  christos 	      while (num--)
    632  1.5  christos 		{
    633  1.5  christos 		  ARMul_StoreWordN (state, address, VFP_uword (sreg));
    634  1.5  christos 		  address += 4;
    635  1.5  christos 		  sreg += 1;
    636  1.5  christos 		}
    637  1.5  christos 	    }
    638  1.5  christos 	}
    639  1.5  christos       else if (BITS (9, 11) != 0x5)
    640  1.5  christos 	break;
    641  1.5  christos       else
    642  1.5  christos 	{
    643  1.5  christos 	  /* VSTM PUW=101 */
    644  1.5  christos 	  int n = BITS (16, 19);
    645  1.5  christos 	  int imm8 = BITS (0, 7);
    646  1.5  christos 	  ARMword address = state->Reg[n] - (imm8 << 2);
    647  1.5  christos 	  state->Reg[n] = address;
    648  1.5  christos 
    649  1.5  christos 	  if (BIT (8))
    650  1.5  christos 	    {
    651  1.5  christos 	      int src = (BIT (22) << 4) | BITS (12, 15);
    652  1.5  christos 
    653  1.5  christos 	      imm8 >>= 1;
    654  1.5  christos 	      while (imm8--)
    655  1.5  christos 		{
    656  1.5  christos 		  if (state->bigendSig)
    657  1.5  christos 		    {
    658  1.5  christos 		      ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
    659  1.5  christos 		      ARMul_StoreWordN (state, address + 4, VFP_dword (src));
    660  1.5  christos 		    }
    661  1.5  christos 		  else
    662  1.5  christos 		    {
    663  1.5  christos 		      ARMul_StoreWordN (state, address, VFP_dword (src));
    664  1.5  christos 		      ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
    665  1.5  christos 		    }
    666  1.5  christos 		  address += 8;
    667  1.5  christos 		  src += 1;
    668  1.5  christos 		}
    669  1.5  christos 	    }
    670  1.5  christos 	  else
    671  1.5  christos 	    {
    672  1.5  christos 	      int src = (BITS (12, 15) << 1) | BIT (22);
    673  1.5  christos 
    674  1.5  christos 	      while (imm8--)
    675  1.5  christos 		{
    676  1.5  christos 		  ARMul_StoreWordN (state, address, VFP_uword (src));
    677  1.5  christos 		  address += 4;
    678  1.5  christos 		  src += 1;
    679  1.5  christos 		}
    680  1.5  christos 	    }
    681  1.5  christos 	}
    682  1.5  christos       return;
    683  1.5  christos 
    684  1.5  christos     case 0x13:
    685  1.5  christos     case 0x17:
    686  1.5  christos       /* VLDM PUW=101 */
    687  1.5  christos     case 0x09:
    688  1.5  christos     case 0x0D:
    689  1.5  christos       /* VLDM PUW=010 */
    690  1.5  christos 	{
    691  1.5  christos 	  int n = BITS (16, 19);
    692  1.5  christos 	  int imm8 = BITS (0, 7);
    693  1.5  christos 
    694  1.5  christos 	  ARMword address = state->Reg[n];
    695  1.5  christos 	  if (BIT (23) == 0)
    696  1.5  christos 	    address -= imm8 << 2;
    697  1.5  christos 	  if (BIT (21))
    698  1.5  christos 	    state->Reg[n] = BIT (23) ? address + (imm8 << 2) : address;
    699  1.5  christos 
    700  1.5  christos 	  if (BIT (8))
    701  1.5  christos 	    {
    702  1.5  christos 	      int dest = (BIT (22) << 4) | BITS (12, 15);
    703  1.5  christos 	      imm8 >>= 1;
    704  1.5  christos 	      while (imm8--)
    705  1.5  christos 		{
    706  1.5  christos 		  if (state->bigendSig)
    707  1.5  christos 		    {
    708  1.5  christos 		      VFP_dword (dest) = ARMul_LoadWordN (state, address);
    709  1.5  christos 		      VFP_dword (dest) <<= 32;
    710  1.5  christos 		      VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
    711  1.5  christos 		    }
    712  1.5  christos 		  else
    713  1.5  christos 		    {
    714  1.5  christos 		      VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
    715  1.5  christos 		      VFP_dword (dest) <<= 32;
    716  1.5  christos 		      VFP_dword (dest) |= ARMul_LoadWordN (state, address);
    717  1.5  christos 		    }
    718  1.5  christos 
    719  1.5  christos 		  if (trace)
    720  1.5  christos 		    fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
    721  1.5  christos 
    722  1.5  christos 		  address += 8;
    723  1.5  christos 		  dest += 1;
    724  1.5  christos 		}
    725  1.5  christos 	    }
    726  1.5  christos 	  else
    727  1.5  christos 	    {
    728  1.5  christos 	      int dest = (BITS (12, 15) << 1) | BIT (22);
    729  1.5  christos 
    730  1.5  christos 	      while (imm8--)
    731  1.5  christos 		{
    732  1.5  christos 		  VFP_uword (dest) = ARMul_LoadWordN (state, address);
    733  1.5  christos 		  address += 4;
    734  1.5  christos 		  dest += 1;
    735  1.5  christos 		}
    736  1.5  christos 	    }
    737  1.5  christos 	}
    738  1.5  christos       return;
    739  1.5  christos 
    740  1.5  christos     case 0x0B:
    741  1.5  christos     case 0x0F:
    742  1.5  christos       if (BITS (16, 19) == 13)
    743  1.5  christos 	{
    744  1.5  christos 	  /* VPOP */
    745  1.5  christos 	  ARMword address = state->Reg[13];
    746  1.5  christos 	  state->Reg[13] = address + (BITS (0, 7) << 2);
    747  1.5  christos 
    748  1.5  christos 	  if (BIT (8))
    749  1.5  christos 	    {
    750  1.5  christos 	      int dest = (BIT (22) << 4) | BITS (12, 15);
    751  1.5  christos 	      int num  = BITS (0, 7) >> 1;
    752  1.5  christos 
    753  1.5  christos 	      while (num--)
    754  1.5  christos 		{
    755  1.5  christos 		  if (state->bigendSig)
    756  1.5  christos 		    {
    757  1.5  christos 		      VFP_dword (dest) = ARMul_LoadWordN (state, address);
    758  1.5  christos 		      VFP_dword (dest) <<= 32;
    759  1.5  christos 		      VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
    760  1.5  christos 		    }
    761  1.5  christos 		  else
    762  1.5  christos 		    {
    763  1.5  christos 		      VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
    764  1.5  christos 		      VFP_dword (dest) <<= 32;
    765  1.5  christos 		      VFP_dword (dest) |= ARMul_LoadWordN (state, address);
    766  1.5  christos 		    }
    767  1.5  christos 
    768  1.5  christos 		  if (trace)
    769  1.5  christos 		    fprintf (stderr, " VFP: VPOP: D%d = %g\n", dest, VFP_dval (dest));
    770  1.5  christos 
    771  1.5  christos 		  address += 8;
    772  1.5  christos 		  dest += 1;
    773  1.5  christos 		}
    774  1.5  christos 	    }
    775  1.5  christos 	  else
    776  1.5  christos 	    {
    777  1.5  christos 	      int sreg = (BITS (12, 15) << 1) | BIT (22);
    778  1.5  christos 	      int num  = BITS (0, 7);
    779  1.5  christos 
    780  1.5  christos 	      while (num--)
    781  1.5  christos 		{
    782  1.5  christos 		  VFP_uword (sreg) = ARMul_LoadWordN (state, address);
    783  1.5  christos 		  address += 4;
    784  1.5  christos 		  sreg += 1;
    785  1.5  christos 		}
    786  1.5  christos 	    }
    787  1.5  christos 	}
    788  1.5  christos       else if (BITS (9, 11) != 0x5)
    789  1.5  christos 	break;
    790  1.5  christos       else
    791  1.5  christos 	{
    792  1.5  christos 	  /* VLDM PUW=011 */
    793  1.5  christos 	  int n = BITS (16, 19);
    794  1.5  christos 	  int imm8 = BITS (0, 7);
    795  1.5  christos 	  ARMword address = state->Reg[n];
    796  1.5  christos 	  state->Reg[n] += imm8 << 2;
    797  1.5  christos 
    798  1.5  christos 	  if (BIT (8))
    799  1.5  christos 	    {
    800  1.5  christos 	      int dest = (BIT (22) << 4) | BITS (12, 15);
    801  1.5  christos 
    802  1.5  christos 	      imm8 >>= 1;
    803  1.5  christos 	      while (imm8--)
    804  1.5  christos 		{
    805  1.5  christos 		  if (state->bigendSig)
    806  1.5  christos 		    {
    807  1.5  christos 		      VFP_dword (dest) = ARMul_LoadWordN (state, address);
    808  1.5  christos 		      VFP_dword (dest) <<= 32;
    809  1.5  christos 		      VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
    810  1.5  christos 		    }
    811  1.5  christos 		  else
    812  1.5  christos 		    {
    813  1.5  christos 		      VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
    814  1.5  christos 		      VFP_dword (dest) <<= 32;
    815  1.5  christos 		      VFP_dword (dest) |= ARMul_LoadWordN (state, address);
    816  1.5  christos 		    }
    817  1.5  christos 
    818  1.5  christos 		  if (trace)
    819  1.5  christos 		    fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
    820  1.5  christos 
    821  1.5  christos 		  address += 8;
    822  1.5  christos 		  dest += 1;
    823  1.5  christos 		}
    824  1.5  christos 	    }
    825  1.5  christos 	  else
    826  1.5  christos 	    {
    827  1.5  christos 	      int dest = (BITS (12, 15) << 1) | BIT (22);
    828  1.5  christos 	      while (imm8--)
    829  1.5  christos 		{
    830  1.5  christos 		  VFP_uword (dest) = ARMul_LoadWordN (state, address);
    831  1.5  christos 		  address += 4;
    832  1.5  christos 		  dest += 1;
    833  1.5  christos 		}
    834  1.5  christos 	    }
    835  1.5  christos 	}
    836  1.5  christos       return;
    837  1.5  christos 
    838  1.5  christos     case 0x11:
    839  1.5  christos     case 0x15:
    840  1.5  christos     case 0x19:
    841  1.5  christos     case 0x1D:
    842  1.5  christos       {
    843  1.5  christos 	/* VLDR */
    844  1.5  christos 	ARMword imm32 = BITS (0, 7) << 2;
    845  1.5  christos 	int base = state->Reg[LHSReg];
    846  1.5  christos 	ARMword address;
    847  1.5  christos 	int dest;
    848  1.5  christos 
    849  1.5  christos 	if (LHSReg == 15)
    850  1.5  christos 	  base = (base + 3) & ~3;
    851  1.5  christos 
    852  1.5  christos 	address = base + (BIT (23) ? imm32 : - imm32);
    853  1.5  christos 
    854  1.5  christos 	if (CPNum == 10)
    855  1.5  christos 	  {
    856  1.5  christos 	    dest = (DESTReg << 1) + BIT (22);
    857  1.5  christos 
    858  1.5  christos 	    VFP_uword (dest) = ARMul_LoadWordN (state, address);
    859  1.5  christos 	  }
    860  1.5  christos 	else
    861  1.5  christos 	  {
    862  1.5  christos 	    dest = (BIT (22) << 4) + DESTReg;
    863  1.5  christos 
    864  1.5  christos 	    if (state->bigendSig)
    865  1.5  christos 	      {
    866  1.5  christos 		VFP_dword (dest) = ARMul_LoadWordN (state, address);
    867  1.5  christos 		VFP_dword (dest) <<= 32;
    868  1.5  christos 		VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
    869  1.5  christos 	      }
    870  1.5  christos 	    else
    871  1.5  christos 	      {
    872  1.5  christos 		VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
    873  1.5  christos 		VFP_dword (dest) <<= 32;
    874  1.5  christos 		VFP_dword (dest) |= ARMul_LoadWordN (state, address);
    875  1.5  christos 	      }
    876  1.5  christos 
    877  1.5  christos 	    if (trace)
    878  1.5  christos 	      fprintf (stderr, " VFP: VLDR: D%d = %g\n", dest, VFP_dval (dest));
    879  1.5  christos 	  }
    880  1.5  christos       }
    881  1.5  christos       return;
    882  1.5  christos     }
    883  1.5  christos 
    884  1.5  christos   fprintf (stderr, "SIM: VFP: Unimplemented: %0x\n", BITS (20, 24));
    885  1.5  christos }
    886  1.5  christos 
    887  1.1  christos /* This function does the work of generating the addresses used in an
    888  1.1  christos    LDC instruction.  The code here is always post-indexed, it's up to the
    889  1.1  christos    caller to get the input address correct and to handle base register
    890  1.1  christos    modification. It also handles the Busy-Waiting.  */
    891  1.1  christos 
    892  1.1  christos void
    893  1.1  christos ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
    894  1.1  christos {
    895  1.1  christos   unsigned cpab;
    896  1.1  christos   ARMword data;
    897  1.1  christos 
    898  1.5  christos   if (CPNum == 10 || CPNum == 11)
    899  1.5  christos     {
    900  1.5  christos       handle_VFP_xfer (state, instr);
    901  1.5  christos       return;
    902  1.5  christos     }
    903  1.5  christos 
    904  1.1  christos   UNDEF_LSCPCBaseWb;
    905  1.1  christos 
    906  1.1  christos   if (! CP_ACCESS_ALLOWED (state, CPNum))
    907  1.1  christos     {
    908  1.1  christos       ARMul_UndefInstr (state, instr);
    909  1.1  christos       return;
    910  1.1  christos     }
    911  1.1  christos 
    912  1.1  christos   if (ADDREXCEPT (address))
    913  1.1  christos     INTERNALABORT (address);
    914  1.1  christos 
    915  1.1  christos   cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
    916  1.1  christos   while (cpab == ARMul_BUSY)
    917  1.1  christos     {
    918  1.1  christos       ARMul_Icycles (state, 1, 0);
    919  1.1  christos 
    920  1.1  christos       if (IntPending (state))
    921  1.1  christos 	{
    922  1.1  christos 	  cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
    923  1.1  christos 	  return;
    924  1.1  christos 	}
    925  1.1  christos       else
    926  1.1  christos 	cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
    927  1.1  christos     }
    928  1.1  christos   if (cpab == ARMul_CANT)
    929  1.1  christos     {
    930  1.1  christos       CPTAKEABORT;
    931  1.1  christos       return;
    932  1.1  christos     }
    933  1.1  christos 
    934  1.1  christos   cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
    935  1.1  christos   data = ARMul_LoadWordN (state, address);
    936  1.1  christos   BUSUSEDINCPCN;
    937  1.1  christos 
    938  1.1  christos   if (BIT (21))
    939  1.1  christos     LSBase = state->Base;
    940  1.1  christos   cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
    941  1.1  christos 
    942  1.1  christos   while (cpab == ARMul_INC)
    943  1.1  christos     {
    944  1.1  christos       address += 4;
    945  1.1  christos       data = ARMul_LoadWordN (state, address);
    946  1.1  christos       cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
    947  1.1  christos     }
    948  1.1  christos 
    949  1.1  christos   if (state->abortSig || state->Aborted)
    950  1.1  christos     TAKEABORT;
    951  1.1  christos }
    952  1.1  christos 
    953  1.1  christos /* This function does the work of generating the addresses used in an
    954  1.1  christos    STC instruction.  The code here is always post-indexed, it's up to the
    955  1.1  christos    caller to get the input address correct and to handle base register
    956  1.1  christos    modification. It also handles the Busy-Waiting.  */
    957  1.1  christos 
    958  1.1  christos void
    959  1.1  christos ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
    960  1.1  christos {
    961  1.1  christos   unsigned cpab;
    962  1.1  christos   ARMword data;
    963  1.1  christos 
    964  1.5  christos   if (CPNum == 10 || CPNum == 11)
    965  1.5  christos     {
    966  1.5  christos       handle_VFP_xfer (state, instr);
    967  1.5  christos       return;
    968  1.5  christos     }
    969  1.5  christos 
    970  1.1  christos   UNDEF_LSCPCBaseWb;
    971  1.1  christos 
    972  1.1  christos   if (! CP_ACCESS_ALLOWED (state, CPNum))
    973  1.1  christos     {
    974  1.1  christos       ARMul_UndefInstr (state, instr);
    975  1.1  christos       return;
    976  1.1  christos     }
    977  1.1  christos 
    978  1.1  christos   if (ADDREXCEPT (address) || VECTORACCESS (address))
    979  1.1  christos     INTERNALABORT (address);
    980  1.1  christos 
    981  1.1  christos   cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
    982  1.1  christos   while (cpab == ARMul_BUSY)
    983  1.1  christos     {
    984  1.1  christos       ARMul_Icycles (state, 1, 0);
    985  1.1  christos       if (IntPending (state))
    986  1.1  christos 	{
    987  1.1  christos 	  cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
    988  1.1  christos 	  return;
    989  1.1  christos 	}
    990  1.1  christos       else
    991  1.1  christos 	cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
    992  1.1  christos     }
    993  1.1  christos 
    994  1.1  christos   if (cpab == ARMul_CANT)
    995  1.1  christos     {
    996  1.1  christos       CPTAKEABORT;
    997  1.1  christos       return;
    998  1.1  christos     }
    999  1.1  christos #ifndef MODE32
   1000  1.1  christos   if (ADDREXCEPT (address) || VECTORACCESS (address))
   1001  1.1  christos     INTERNALABORT (address);
   1002  1.1  christos #endif
   1003  1.1  christos   BUSUSEDINCPCN;
   1004  1.1  christos   if (BIT (21))
   1005  1.1  christos     LSBase = state->Base;
   1006  1.1  christos   cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
   1007  1.1  christos   ARMul_StoreWordN (state, address, data);
   1008  1.1  christos 
   1009  1.1  christos   while (cpab == ARMul_INC)
   1010  1.1  christos     {
   1011  1.1  christos       address += 4;
   1012  1.1  christos       cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
   1013  1.1  christos       ARMul_StoreWordN (state, address, data);
   1014  1.1  christos     }
   1015  1.1  christos 
   1016  1.1  christos   if (state->abortSig || state->Aborted)
   1017  1.1  christos     TAKEABORT;
   1018  1.1  christos }
   1019  1.1  christos 
   1020  1.1  christos /* This function does the Busy-Waiting for an MCR instruction.  */
   1021  1.1  christos 
   1022  1.1  christos void
   1023  1.1  christos ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
   1024  1.1  christos {
   1025  1.1  christos   unsigned cpab;
   1026  1.1  christos 
   1027  1.1  christos   if (! CP_ACCESS_ALLOWED (state, CPNum))
   1028  1.1  christos     {
   1029  1.1  christos       ARMul_UndefInstr (state, instr);
   1030  1.1  christos       return;
   1031  1.1  christos     }
   1032  1.1  christos 
   1033  1.1  christos   cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
   1034  1.1  christos 
   1035  1.1  christos   while (cpab == ARMul_BUSY)
   1036  1.1  christos     {
   1037  1.1  christos       ARMul_Icycles (state, 1, 0);
   1038  1.1  christos 
   1039  1.1  christos       if (IntPending (state))
   1040  1.1  christos 	{
   1041  1.1  christos 	  cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
   1042  1.1  christos 	  return;
   1043  1.1  christos 	}
   1044  1.1  christos       else
   1045  1.1  christos 	cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
   1046  1.1  christos     }
   1047  1.1  christos 
   1048  1.1  christos   if (cpab == ARMul_CANT)
   1049  1.1  christos     ARMul_Abort (state, ARMul_UndefinedInstrV);
   1050  1.1  christos   else
   1051  1.1  christos     {
   1052  1.1  christos       BUSUSEDINCPCN;
   1053  1.1  christos       ARMul_Ccycles (state, 1, 0);
   1054  1.1  christos     }
   1055  1.1  christos }
   1056  1.1  christos 
   1057  1.1  christos /* This function does the Busy-Waiting for an MRC instruction.  */
   1058  1.1  christos 
   1059  1.1  christos ARMword
   1060  1.1  christos ARMul_MRC (ARMul_State * state, ARMword instr)
   1061  1.1  christos {
   1062  1.1  christos   unsigned cpab;
   1063  1.1  christos   ARMword result = 0;
   1064  1.1  christos 
   1065  1.1  christos   if (! CP_ACCESS_ALLOWED (state, CPNum))
   1066  1.1  christos     {
   1067  1.1  christos       ARMul_UndefInstr (state, instr);
   1068  1.1  christos       return result;
   1069  1.1  christos     }
   1070  1.1  christos 
   1071  1.1  christos   cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
   1072  1.1  christos   while (cpab == ARMul_BUSY)
   1073  1.1  christos     {
   1074  1.1  christos       ARMul_Icycles (state, 1, 0);
   1075  1.1  christos       if (IntPending (state))
   1076  1.1  christos 	{
   1077  1.1  christos 	  cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
   1078  1.1  christos 	  return (0);
   1079  1.1  christos 	}
   1080  1.1  christos       else
   1081  1.1  christos 	cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
   1082  1.1  christos     }
   1083  1.1  christos   if (cpab == ARMul_CANT)
   1084  1.1  christos     {
   1085  1.1  christos       ARMul_Abort (state, ARMul_UndefinedInstrV);
   1086  1.1  christos       /* Parent will destroy the flags otherwise.  */
   1087  1.1  christos       result = ECC;
   1088  1.1  christos     }
   1089  1.1  christos   else
   1090  1.1  christos     {
   1091  1.1  christos       BUSUSEDINCPCN;
   1092  1.1  christos       ARMul_Ccycles (state, 1, 0);
   1093  1.1  christos       ARMul_Icycles (state, 1, 0);
   1094  1.1  christos     }
   1095  1.1  christos 
   1096  1.1  christos   return result;
   1097  1.1  christos }
   1098  1.1  christos 
   1099  1.5  christos static void
   1100  1.5  christos handle_VFP_op (ARMul_State * state, ARMword instr)
   1101  1.5  christos {
   1102  1.5  christos   int dest;
   1103  1.5  christos   int srcN;
   1104  1.5  christos   int srcM;
   1105  1.5  christos 
   1106  1.5  christos   if (BITS (9, 11) != 0x5 || BIT (4) != 0)
   1107  1.5  christos     {
   1108  1.5  christos       fprintf (stderr, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31));
   1109  1.5  christos       return;
   1110  1.5  christos     }
   1111  1.5  christos 
   1112  1.5  christos   if (BIT (8))
   1113  1.5  christos     {
   1114  1.5  christos       dest = BITS(12,15) + (BIT (22) << 4);
   1115  1.5  christos       srcN = LHSReg  + (BIT (7) << 4);
   1116  1.5  christos       srcM = BITS (0,3) + (BIT (5) << 4);
   1117  1.5  christos     }
   1118  1.5  christos   else
   1119  1.5  christos     {
   1120  1.5  christos       dest = (BITS(12,15) << 1) + BIT (22);
   1121  1.5  christos       srcN = (LHSReg << 1) + BIT (7);
   1122  1.5  christos       srcM = (BITS (0,3) << 1) + BIT (5);
   1123  1.5  christos     }
   1124  1.5  christos 
   1125  1.5  christos   switch (BITS (20, 27))
   1126  1.5  christos     {
   1127  1.5  christos     case 0xE0:
   1128  1.5  christos     case 0xE4:
   1129  1.5  christos       /* VMLA VMLS */
   1130  1.5  christos       if (BIT (8))
   1131  1.5  christos 	{
   1132  1.5  christos 	  ARMdval val = VFP_dval (srcN) * VFP_dval (srcM);
   1133  1.5  christos 
   1134  1.5  christos 	  if (BIT (6))
   1135  1.5  christos 	    {
   1136  1.5  christos 	      if (trace)
   1137  1.5  christos 		fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n",
   1138  1.6  christos 			 VFP_dval (dest) - val,
   1139  1.5  christos 			 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
   1140  1.5  christos 	      VFP_dval (dest) -= val;
   1141  1.5  christos 	    }
   1142  1.5  christos 	  else
   1143  1.5  christos 	    {
   1144  1.5  christos 	      if (trace)
   1145  1.5  christos 		fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n",
   1146  1.6  christos 			 VFP_dval (dest) + val,
   1147  1.5  christos 			 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
   1148  1.5  christos 	      VFP_dval (dest) += val;
   1149  1.5  christos 	    }
   1150  1.5  christos 	}
   1151  1.5  christos       else
   1152  1.5  christos 	{
   1153  1.5  christos 	  ARMfval val = VFP_fval (srcN) * VFP_fval (srcM);
   1154  1.5  christos 
   1155  1.5  christos 	  if (BIT (6))
   1156  1.5  christos 	    {
   1157  1.5  christos 	      if (trace)
   1158  1.5  christos 		fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n",
   1159  1.6  christos 			 VFP_fval (dest) - val,
   1160  1.5  christos 			 VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM));
   1161  1.5  christos 	      VFP_fval (dest) -= val;
   1162  1.5  christos 	    }
   1163  1.5  christos 	  else
   1164  1.5  christos 	    {
   1165  1.5  christos 	      if (trace)
   1166  1.5  christos 		fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n",
   1167  1.6  christos 			 VFP_fval (dest) + val,
   1168  1.5  christos 			 VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM));
   1169  1.5  christos 	      VFP_fval (dest) += val;
   1170  1.5  christos 	    }
   1171  1.5  christos 	}
   1172  1.5  christos       return;
   1173  1.5  christos 
   1174  1.5  christos     case 0xE1:
   1175  1.5  christos     case 0xE5:
   1176  1.5  christos       if (BIT (8))
   1177  1.5  christos 	{
   1178  1.5  christos 	  ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
   1179  1.5  christos 
   1180  1.5  christos 	  if (BIT (6))
   1181  1.5  christos 	    {
   1182  1.5  christos 	      /* VNMLA */
   1183  1.5  christos 	      if (trace)
   1184  1.5  christos 		fprintf (stderr, " VFP: VNMLA: %g = -(%g + (%g * %g))\n",
   1185  1.5  christos 			 -(VFP_dval (dest) + product),
   1186  1.5  christos 			 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
   1187  1.5  christos 	      VFP_dval (dest) = -(product + VFP_dval (dest));
   1188  1.5  christos 	    }
   1189  1.5  christos 	  else
   1190  1.5  christos 	    {
   1191  1.5  christos 	      /* VNMLS */
   1192  1.5  christos 	      if (trace)
   1193  1.5  christos 		fprintf (stderr, " VFP: VNMLS: %g = -(%g + (%g * %g))\n",
   1194  1.5  christos 			 -(VFP_dval (dest) + product),
   1195  1.5  christos 			 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
   1196  1.5  christos 	      VFP_dval (dest) = product - VFP_dval (dest);
   1197  1.5  christos 	    }
   1198  1.5  christos 	}
   1199  1.5  christos       else
   1200  1.5  christos 	{
   1201  1.5  christos 	  ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
   1202  1.5  christos 
   1203  1.5  christos 	  if (BIT (6))
   1204  1.5  christos 	    /* VNMLA */
   1205  1.5  christos 	    VFP_fval (dest) = -(product + VFP_fval (dest));
   1206  1.5  christos 	  else
   1207  1.5  christos 	    /* VNMLS */
   1208  1.5  christos 	    VFP_fval (dest) = product - VFP_fval (dest);
   1209  1.5  christos 	}
   1210  1.5  christos       return;
   1211  1.5  christos 
   1212  1.5  christos     case 0xE2:
   1213  1.5  christos     case 0xE6:
   1214  1.5  christos       if (BIT (8))
   1215  1.5  christos 	{
   1216  1.5  christos 	  ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
   1217  1.5  christos 
   1218  1.5  christos 	  if (BIT (6))
   1219  1.5  christos 	    {
   1220  1.5  christos 	      if (trace)
   1221  1.5  christos 		fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
   1222  1.5  christos 			 - product, VFP_dval (srcN), VFP_dval (srcM));
   1223  1.5  christos 	      /* VNMUL */
   1224  1.5  christos 	      VFP_dval (dest) = - product;
   1225  1.5  christos 	    }
   1226  1.5  christos 	  else
   1227  1.5  christos 	    {
   1228  1.5  christos 	      if (trace)
   1229  1.5  christos 		fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
   1230  1.5  christos 			 product, VFP_dval (srcN), VFP_dval (srcM));
   1231  1.5  christos 	      /* VMUL */
   1232  1.5  christos 	      VFP_dval (dest) = product;
   1233  1.5  christos 	    }
   1234  1.5  christos 	}
   1235  1.5  christos       else
   1236  1.5  christos 	{
   1237  1.5  christos 	  ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
   1238  1.5  christos 
   1239  1.5  christos 	  if (BIT (6))
   1240  1.5  christos 	    {
   1241  1.5  christos 	      if (trace)
   1242  1.5  christos 		fprintf (stderr, " VFP: VNMUL: %g = %g * %g\n",
   1243  1.5  christos 			 - product, VFP_fval (srcN), VFP_fval (srcM));
   1244  1.5  christos 
   1245  1.5  christos 	      VFP_fval (dest) = - product;
   1246  1.5  christos 	    }
   1247  1.5  christos 	  else
   1248  1.5  christos 	    {
   1249  1.5  christos 	      if (trace)
   1250  1.5  christos 		fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
   1251  1.5  christos 			 product, VFP_fval (srcN), VFP_fval (srcM));
   1252  1.5  christos 
   1253  1.5  christos 	      VFP_fval (dest) = product;
   1254  1.5  christos 	    }
   1255  1.5  christos 	}
   1256  1.5  christos       return;
   1257  1.5  christos 
   1258  1.5  christos     case 0xE3:
   1259  1.5  christos     case 0xE7:
   1260  1.5  christos       if (BIT (6) == 0)
   1261  1.5  christos 	{
   1262  1.5  christos 	  /* VADD */
   1263  1.5  christos 	  if (BIT(8))
   1264  1.5  christos 	    {
   1265  1.5  christos 	      if (trace)
   1266  1.5  christos 		fprintf (stderr, " VFP: VADD %g = %g + %g\n",
   1267  1.5  christos 			 VFP_dval (srcN) + VFP_dval (srcM),
   1268  1.5  christos 			 VFP_dval (srcN),
   1269  1.5  christos 			 VFP_dval (srcM));
   1270  1.5  christos 	      VFP_dval (dest) = VFP_dval (srcN) + VFP_dval (srcM);
   1271  1.5  christos 	    }
   1272  1.5  christos 	  else
   1273  1.5  christos 	    VFP_fval (dest) = VFP_fval (srcN) + VFP_fval (srcM);
   1274  1.5  christos 
   1275  1.5  christos 	}
   1276  1.5  christos       else
   1277  1.5  christos 	{
   1278  1.5  christos 	  /* VSUB */
   1279  1.5  christos 	  if (BIT(8))
   1280  1.5  christos 	    {
   1281  1.5  christos 	      if (trace)
   1282  1.5  christos 		fprintf (stderr, " VFP: VSUB %g = %g - %g\n",
   1283  1.5  christos 			 VFP_dval (srcN) - VFP_dval (srcM),
   1284  1.5  christos 			 VFP_dval (srcN),
   1285  1.5  christos 			 VFP_dval (srcM));
   1286  1.5  christos 	      VFP_dval (dest) = VFP_dval (srcN) - VFP_dval (srcM);
   1287  1.5  christos 	    }
   1288  1.5  christos 	  else
   1289  1.5  christos 	    VFP_fval (dest) = VFP_fval (srcN) - VFP_fval (srcM);
   1290  1.5  christos 	}
   1291  1.5  christos       return;
   1292  1.5  christos 
   1293  1.5  christos     case 0xE8:
   1294  1.5  christos     case 0xEC:
   1295  1.5  christos       if (BIT (6) == 1)
   1296  1.5  christos 	break;
   1297  1.5  christos 
   1298  1.5  christos       /* VDIV */
   1299  1.5  christos       if (BIT (8))
   1300  1.5  christos 	{
   1301  1.5  christos 	  ARMdval res = VFP_dval (srcN) / VFP_dval (srcM);
   1302  1.5  christos 	  if (trace)
   1303  1.5  christos 	    fprintf (stderr, " VFP: VDIV (64bit): %g = %g / %g\n",
   1304  1.5  christos 		     res, VFP_dval (srcN), VFP_dval (srcM));
   1305  1.5  christos 	  VFP_dval (dest) = res;
   1306  1.5  christos 	}
   1307  1.5  christos       else
   1308  1.5  christos 	{
   1309  1.5  christos 	  if (trace)
   1310  1.5  christos 	    fprintf (stderr, " VFP: VDIV: %g = %g / %g\n",
   1311  1.5  christos 		     VFP_fval (srcN) / VFP_fval (srcM),
   1312  1.5  christos 		     VFP_fval (srcN), VFP_fval (srcM));
   1313  1.5  christos 
   1314  1.5  christos 	  VFP_fval (dest) = VFP_fval (srcN) / VFP_fval (srcM);
   1315  1.5  christos 	}
   1316  1.5  christos       return;
   1317  1.5  christos 
   1318  1.5  christos     case 0xEB:
   1319  1.5  christos     case 0xEF:
   1320  1.5  christos       if (BIT (6) != 1)
   1321  1.5  christos 	break;
   1322  1.5  christos 
   1323  1.5  christos       switch (BITS (16, 19))
   1324  1.5  christos 	{
   1325  1.5  christos 	case 0x0:
   1326  1.5  christos 	  if (BIT (7) == 0)
   1327  1.5  christos 	    {
   1328  1.5  christos 	      if (BIT (8))
   1329  1.5  christos 		{
   1330  1.5  christos 		  /* VMOV.F64 <Dd>, <Dm>.  */
   1331  1.5  christos 		  VFP_dval (dest) = VFP_dval (srcM);
   1332  1.5  christos 		  if (trace)
   1333  1.5  christos 		    fprintf (stderr, " VFP: VMOV d%d, d%d: %g\n", dest, srcM, VFP_dval (srcM));
   1334  1.5  christos 		}
   1335  1.5  christos 	      else
   1336  1.5  christos 		{
   1337  1.5  christos 		  /* VMOV.F32 <Sd>, <Sm>.  */
   1338  1.5  christos 		  VFP_fval (dest) = VFP_fval (srcM);
   1339  1.5  christos 		  if (trace)
   1340  1.5  christos 		    fprintf (stderr, " VFP: VMOV s%d, s%d: %g\n", dest, srcM, VFP_fval (srcM));
   1341  1.5  christos 		}
   1342  1.5  christos 	    }
   1343  1.5  christos 	  else
   1344  1.5  christos 	    {
   1345  1.5  christos 	      /* VABS */
   1346  1.5  christos 	      if (BIT (8))
   1347  1.5  christos 		{
   1348  1.5  christos 		  ARMdval src = VFP_dval (srcM);
   1349  1.6  christos 
   1350  1.5  christos 		  VFP_dval (dest) = fabs (src);
   1351  1.5  christos 		  if (trace)
   1352  1.5  christos 		    fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_dval (dest));
   1353  1.5  christos 		}
   1354  1.5  christos 	      else
   1355  1.5  christos 		{
   1356  1.5  christos 		  ARMfval src = VFP_fval (srcM);
   1357  1.5  christos 
   1358  1.5  christos 		  VFP_fval (dest) = fabsf (src);
   1359  1.5  christos 		  if (trace)
   1360  1.5  christos 		    fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_fval (dest));
   1361  1.5  christos 		}
   1362  1.5  christos 	    }
   1363  1.5  christos 	  return;
   1364  1.5  christos 
   1365  1.5  christos 	case 0x1:
   1366  1.5  christos 	  if (BIT (7) == 0)
   1367  1.5  christos 	    {
   1368  1.5  christos 	      /* VNEG */
   1369  1.5  christos 	      if (BIT (8))
   1370  1.5  christos 		VFP_dval (dest) = - VFP_dval (srcM);
   1371  1.5  christos 	      else
   1372  1.5  christos 		VFP_fval (dest) = - VFP_fval (srcM);
   1373  1.5  christos 	    }
   1374  1.5  christos 	  else
   1375  1.5  christos 	    {
   1376  1.5  christos 	      /* VSQRT */
   1377  1.5  christos 	      if (BIT (8))
   1378  1.5  christos 		{
   1379  1.5  christos 		  if (trace)
   1380  1.5  christos 		    fprintf (stderr, " VFP: %g = root(%g)\n",
   1381  1.5  christos 			     sqrt (VFP_dval (srcM)), VFP_dval (srcM));
   1382  1.5  christos 
   1383  1.5  christos 		  VFP_dval (dest) = sqrt (VFP_dval (srcM));
   1384  1.5  christos 		}
   1385  1.5  christos 	      else
   1386  1.5  christos 		{
   1387  1.5  christos 		  if (trace)
   1388  1.5  christos 		    fprintf (stderr, " VFP: %g = root(%g)\n",
   1389  1.5  christos 			     sqrtf (VFP_fval (srcM)), VFP_fval (srcM));
   1390  1.5  christos 
   1391  1.5  christos 		  VFP_fval (dest) = sqrtf (VFP_fval (srcM));
   1392  1.5  christos 		}
   1393  1.5  christos 	    }
   1394  1.5  christos 	  return;
   1395  1.5  christos 
   1396  1.5  christos 	case 0x4:
   1397  1.5  christos 	case 0x5:
   1398  1.5  christos 	  /* VCMP, VCMPE */
   1399  1.5  christos 	  if (BIT(8))
   1400  1.5  christos 	    {
   1401  1.5  christos 	      ARMdval res = VFP_dval (dest);
   1402  1.5  christos 
   1403  1.5  christos 	      if (BIT (16) == 0)
   1404  1.5  christos 		{
   1405  1.5  christos 		  ARMdval src = VFP_dval (srcM);
   1406  1.6  christos 
   1407  1.5  christos 		  if (isinf (res) && isinf (src))
   1408  1.5  christos 		    {
   1409  1.5  christos 		      if (res > 0.0 && src > 0.0)
   1410  1.5  christos 			res = 0.0;
   1411  1.5  christos 		      else if (res < 0.0 && src < 0.0)
   1412  1.5  christos 			res = 0.0;
   1413  1.5  christos 		      /* else leave res alone.   */
   1414  1.5  christos 		    }
   1415  1.5  christos 		  else
   1416  1.5  christos 		    res -= src;
   1417  1.5  christos 		}
   1418  1.5  christos 
   1419  1.5  christos 	      /* FIXME: Add handling of signalling NaNs and the E bit.  */
   1420  1.5  christos 
   1421  1.5  christos 	      state->FPSCR &= 0x0FFFFFFF;
   1422  1.5  christos 	      if (res < 0.0)
   1423  1.5  christos 		state->FPSCR |= NBIT;
   1424  1.5  christos 	      else
   1425  1.5  christos 		state->FPSCR |= CBIT;
   1426  1.5  christos 	      if (res == 0.0)
   1427  1.5  christos 		state->FPSCR |= ZBIT;
   1428  1.5  christos 	      if (isnan (res))
   1429  1.5  christos 		state->FPSCR |= VBIT;
   1430  1.5  christos 
   1431  1.5  christos 	      if (trace)
   1432  1.5  christos 		fprintf (stderr, " VFP: VCMP (64bit) %g vs %g res %g, flags: %c%c%c%c\n",
   1433  1.5  christos 			 VFP_dval (dest), BIT (16) ? 0.0 : VFP_dval (srcM), res,
   1434  1.5  christos 			 state->FPSCR & NBIT ? 'N' : '-',
   1435  1.5  christos 			 state->FPSCR & ZBIT ? 'Z' : '-',
   1436  1.5  christos 			 state->FPSCR & CBIT ? 'C' : '-',
   1437  1.5  christos 			 state->FPSCR & VBIT ? 'V' : '-');
   1438  1.5  christos 	    }
   1439  1.5  christos 	  else
   1440  1.5  christos 	    {
   1441  1.5  christos 	      ARMfval res = VFP_fval (dest);
   1442  1.5  christos 
   1443  1.5  christos 	      if (BIT (16) == 0)
   1444  1.5  christos 		{
   1445  1.5  christos 		  ARMfval src = VFP_fval (srcM);
   1446  1.6  christos 
   1447  1.5  christos 		  if (isinf (res) && isinf (src))
   1448  1.5  christos 		    {
   1449  1.5  christos 		      if (res > 0.0 && src > 0.0)
   1450  1.5  christos 			res = 0.0;
   1451  1.5  christos 		      else if (res < 0.0 && src < 0.0)
   1452  1.5  christos 			res = 0.0;
   1453  1.5  christos 		      /* else leave res alone.   */
   1454  1.5  christos 		    }
   1455  1.5  christos 		  else
   1456  1.5  christos 		    res -= src;
   1457  1.5  christos 		}
   1458  1.5  christos 
   1459  1.5  christos 	      /* FIXME: Add handling of signalling NaNs and the E bit.  */
   1460  1.5  christos 
   1461  1.5  christos 	      state->FPSCR &= 0x0FFFFFFF;
   1462  1.5  christos 	      if (res < 0.0)
   1463  1.5  christos 		state->FPSCR |= NBIT;
   1464  1.5  christos 	      else
   1465  1.5  christos 		state->FPSCR |= CBIT;
   1466  1.5  christos 	      if (res == 0.0)
   1467  1.5  christos 		state->FPSCR |= ZBIT;
   1468  1.5  christos 	      if (isnan (res))
   1469  1.5  christos 		state->FPSCR |= VBIT;
   1470  1.5  christos 
   1471  1.5  christos 	      if (trace)
   1472  1.5  christos 		fprintf (stderr, " VFP: VCMP (32bit) %g vs %g res %g, flags: %c%c%c%c\n",
   1473  1.5  christos 			 VFP_fval (dest), BIT (16) ? 0.0 : VFP_fval (srcM), res,
   1474  1.5  christos 			 state->FPSCR & NBIT ? 'N' : '-',
   1475  1.5  christos 			 state->FPSCR & ZBIT ? 'Z' : '-',
   1476  1.5  christos 			 state->FPSCR & CBIT ? 'C' : '-',
   1477  1.5  christos 			 state->FPSCR & VBIT ? 'V' : '-');
   1478  1.5  christos 	    }
   1479  1.5  christos 	  return;
   1480  1.5  christos 
   1481  1.5  christos 	case 0x7:
   1482  1.5  christos 	  if (BIT (8))
   1483  1.5  christos 	    {
   1484  1.5  christos 	      dest = (DESTReg << 1) + BIT (22);
   1485  1.5  christos 	      VFP_fval (dest) = VFP_dval (srcM);
   1486  1.5  christos 	    }
   1487  1.5  christos 	  else
   1488  1.5  christos 	    {
   1489  1.5  christos 	      dest = DESTReg + (BIT (22) << 4);
   1490  1.5  christos 	      VFP_dval (dest) = VFP_fval (srcM);
   1491  1.5  christos 	    }
   1492  1.5  christos 	  return;
   1493  1.5  christos 
   1494  1.5  christos 	case 0x8:
   1495  1.5  christos 	case 0xC:
   1496  1.5  christos 	case 0xD:
   1497  1.5  christos 	  /* VCVT integer <-> FP */
   1498  1.5  christos 	  if (BIT (18))
   1499  1.5  christos 	    {
   1500  1.5  christos 	      /* To integer.  */
   1501  1.5  christos 	      if (BIT (8))
   1502  1.5  christos 		{
   1503  1.5  christos 		  dest = (BITS(12,15) << 1) + BIT (22);
   1504  1.5  christos 		  if (BIT (16))
   1505  1.5  christos 		    VFP_sword (dest) = VFP_dval (srcM);
   1506  1.5  christos 		  else
   1507  1.5  christos 		    VFP_uword (dest) = VFP_dval (srcM);
   1508  1.5  christos 		}
   1509  1.5  christos 	      else
   1510  1.5  christos 		{
   1511  1.5  christos 		  if (BIT (16))
   1512  1.5  christos 		    VFP_sword (dest) = VFP_fval (srcM);
   1513  1.5  christos 		  else
   1514  1.5  christos 		    VFP_uword (dest) = VFP_fval (srcM);
   1515  1.5  christos 		}
   1516  1.5  christos 	    }
   1517  1.5  christos 	  else
   1518  1.5  christos 	    {
   1519  1.5  christos 	      /* From integer.  */
   1520  1.5  christos 	      if (BIT (8))
   1521  1.5  christos 		{
   1522  1.5  christos 		  srcM = (BITS (0,3) << 1) + BIT (5);
   1523  1.5  christos 		  if (BIT (7))
   1524  1.5  christos 		    VFP_dval (dest) = VFP_sword (srcM);
   1525  1.5  christos 		  else
   1526  1.5  christos 		    VFP_dval (dest) = VFP_uword (srcM);
   1527  1.5  christos 		}
   1528  1.5  christos 	      else
   1529  1.5  christos 		{
   1530  1.5  christos 		  if (BIT (7))
   1531  1.5  christos 		    VFP_fval (dest) = VFP_sword (srcM);
   1532  1.5  christos 		  else
   1533  1.5  christos 		    VFP_fval (dest) = VFP_uword (srcM);
   1534  1.5  christos 		}
   1535  1.5  christos 	    }
   1536  1.5  christos 	  return;
   1537  1.5  christos 	}
   1538  1.5  christos 
   1539  1.5  christos       fprintf (stderr, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27));
   1540  1.5  christos       return;
   1541  1.5  christos     }
   1542  1.5  christos 
   1543  1.5  christos   fprintf (stderr, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27));
   1544  1.5  christos   return;
   1545  1.5  christos }
   1546  1.5  christos 
   1547  1.1  christos /* This function does the Busy-Waiting for an CDP instruction.  */
   1548  1.1  christos 
   1549  1.1  christos void
   1550  1.1  christos ARMul_CDP (ARMul_State * state, ARMword instr)
   1551  1.1  christos {
   1552  1.1  christos   unsigned cpab;
   1553  1.1  christos 
   1554  1.5  christos   if (CPNum == 10 || CPNum == 11)
   1555  1.5  christos     {
   1556  1.5  christos       handle_VFP_op (state, instr);
   1557  1.5  christos       return;
   1558  1.5  christos     }
   1559  1.5  christos 
   1560  1.1  christos   if (! CP_ACCESS_ALLOWED (state, CPNum))
   1561  1.1  christos     {
   1562  1.1  christos       ARMul_UndefInstr (state, instr);
   1563  1.1  christos       return;
   1564  1.1  christos     }
   1565  1.1  christos 
   1566  1.1  christos   cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
   1567  1.1  christos   while (cpab == ARMul_BUSY)
   1568  1.1  christos     {
   1569  1.1  christos       ARMul_Icycles (state, 1, 0);
   1570  1.1  christos       if (IntPending (state))
   1571  1.1  christos 	{
   1572  1.1  christos 	  cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
   1573  1.1  christos 	  return;
   1574  1.1  christos 	}
   1575  1.1  christos       else
   1576  1.1  christos 	cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
   1577  1.1  christos     }
   1578  1.1  christos   if (cpab == ARMul_CANT)
   1579  1.1  christos     ARMul_Abort (state, ARMul_UndefinedInstrV);
   1580  1.1  christos   else
   1581  1.1  christos     BUSUSEDN;
   1582  1.1  christos }
   1583  1.1  christos 
   1584  1.1  christos /* This function handles Undefined instructions, as CP isntruction.  */
   1585  1.1  christos 
   1586  1.1  christos void
   1587  1.1  christos ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
   1588  1.1  christos {
   1589  1.1  christos   ARMul_Abort (state, ARMul_UndefinedInstrV);
   1590  1.1  christos }
   1591  1.1  christos 
   1592  1.1  christos /* Return TRUE if an interrupt is pending, FALSE otherwise.  */
   1593  1.1  christos 
   1594  1.1  christos unsigned
   1595  1.1  christos IntPending (ARMul_State * state)
   1596  1.1  christos {
   1597  1.1  christos   if (state->Exception)
   1598  1.1  christos     {
   1599  1.1  christos       /* Any exceptions.  */
   1600  1.1  christos       if (state->NresetSig == LOW)
   1601  1.1  christos 	{
   1602  1.1  christos 	  ARMul_Abort (state, ARMul_ResetV);
   1603  1.1  christos 	  return TRUE;
   1604  1.1  christos 	}
   1605  1.1  christos       else if (!state->NfiqSig && !FFLAG)
   1606  1.1  christos 	{
   1607  1.1  christos 	  ARMul_Abort (state, ARMul_FIQV);
   1608  1.1  christos 	  return TRUE;
   1609  1.1  christos 	}
   1610  1.1  christos       else if (!state->NirqSig && !IFLAG)
   1611  1.1  christos 	{
   1612  1.1  christos 	  ARMul_Abort (state, ARMul_IRQV);
   1613  1.1  christos 	  return TRUE;
   1614  1.1  christos 	}
   1615  1.1  christos     }
   1616  1.1  christos 
   1617  1.1  christos   return FALSE;
   1618  1.1  christos }
   1619  1.1  christos 
   1620  1.1  christos /* Align a word access to a non word boundary.  */
   1621  1.1  christos 
   1622  1.1  christos ARMword
   1623  1.5  christos ARMul_Align (ARMul_State *state ATTRIBUTE_UNUSED, ARMword address, ARMword data)
   1624  1.1  christos {
   1625  1.1  christos   /* This code assumes the address is really unaligned,
   1626  1.1  christos      as a shift by 32 is undefined in C.  */
   1627  1.1  christos 
   1628  1.1  christos   address = (address & 3) << 3;	/* Get the word address.  */
   1629  1.1  christos   return ((data >> address) | (data << (32 - address)));	/* rot right */
   1630  1.1  christos }
   1631  1.1  christos 
   1632  1.1  christos /* This routine is used to call another routine after a certain number of
   1633  1.1  christos    cycles have been executed. The first parameter is the number of cycles
   1634  1.1  christos    delay before the function is called, the second argument is a pointer
   1635  1.1  christos    to the function. A delay of zero doesn't work, just call the function.  */
   1636  1.1  christos 
   1637  1.1  christos void
   1638  1.1  christos ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
   1639  1.1  christos 		     unsigned (*what) (ARMul_State *))
   1640  1.1  christos {
   1641  1.1  christos   unsigned long when;
   1642  1.1  christos   struct EventNode *event;
   1643  1.1  christos 
   1644  1.1  christos   if (state->EventSet++ == 0)
   1645  1.1  christos     state->Now = ARMul_Time (state);
   1646  1.1  christos   when = (state->Now + delay) % EVENTLISTSIZE;
   1647  1.1  christos   event = (struct EventNode *) malloc (sizeof (struct EventNode));
   1648  1.1  christos   event->func = what;
   1649  1.1  christos   event->next = *(state->EventPtr + when);
   1650  1.1  christos   *(state->EventPtr + when) = event;
   1651  1.1  christos }
   1652  1.1  christos 
   1653  1.1  christos /* This routine is called at the beginning of
   1654  1.1  christos    every cycle, to envoke scheduled events.  */
   1655  1.1  christos 
   1656  1.1  christos void
   1657  1.1  christos ARMul_EnvokeEvent (ARMul_State * state)
   1658  1.1  christos {
   1659  1.1  christos   static unsigned long then;
   1660  1.1  christos 
   1661  1.1  christos   then = state->Now;
   1662  1.1  christos   state->Now = ARMul_Time (state) % EVENTLISTSIZE;
   1663  1.1  christos   if (then < state->Now)
   1664  1.1  christos     /* Schedule events.  */
   1665  1.1  christos     EnvokeList (state, then, state->Now);
   1666  1.1  christos   else if (then > state->Now)
   1667  1.1  christos     {
   1668  1.1  christos       /* Need to wrap around the list.  */
   1669  1.1  christos       EnvokeList (state, then, EVENTLISTSIZE - 1L);
   1670  1.1  christos       EnvokeList (state, 0L, state->Now);
   1671  1.1  christos     }
   1672  1.1  christos }
   1673  1.1  christos 
   1674  1.1  christos /* Envokes all the entries in a range.  */
   1675  1.1  christos 
   1676  1.1  christos static void
   1677  1.1  christos EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
   1678  1.1  christos {
   1679  1.1  christos   for (; from <= to; from++)
   1680  1.1  christos     {
   1681  1.1  christos       struct EventNode *anevent;
   1682  1.1  christos 
   1683  1.1  christos       anevent = *(state->EventPtr + from);
   1684  1.1  christos       while (anevent)
   1685  1.1  christos 	{
   1686  1.1  christos 	  (anevent->func) (state);
   1687  1.1  christos 	  state->EventSet--;
   1688  1.1  christos 	  anevent = anevent->next;
   1689  1.1  christos 	}
   1690  1.1  christos       *(state->EventPtr + from) = NULL;
   1691  1.1  christos     }
   1692  1.1  christos }
   1693  1.1  christos 
   1694  1.1  christos /* This routine is returns the number of clock ticks since the last reset.  */
   1695  1.1  christos 
   1696  1.1  christos unsigned long
   1697  1.1  christos ARMul_Time (ARMul_State * state)
   1698  1.1  christos {
   1699  1.1  christos   return (state->NumScycles + state->NumNcycles +
   1700  1.1  christos 	  state->NumIcycles + state->NumCcycles + state->NumFcycles);
   1701  1.1  christos }
   1702