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