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