/[gxemul]/trunk/src/cpus/cpu_arm_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpus/cpu_arm_instr.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 15 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 16 by dpavlin, Mon Oct 8 16:19:01 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_arm_instr.c,v 1.26 2005/10/07 22:10:51 debug Exp $   *  $Id: cpu_arm_instr.c,v 1.29 2005/10/11 03:31:28 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
# Line 133  Line 133 
133    
134  /*****************************************************************************/  /*****************************************************************************/
135    
 /*  
  *  update_c is set if the C flag should be updated with the last shifted/  
  *  rotated bit.  
  */  
 uint32_t R(struct cpu *cpu, struct arm_instr_call *ic,  
         uint32_t iword, int update_c)  
 {  
         int rm = iword & 15, lastbit, t, c;  
         uint32_t tmp = cpu->cd.arm.r[rm];  
   
         if ((iword & 0xff0)==0 && rm != ARM_PC)  
                 return tmp;  
   
         t = (iword >> 4) & 7;  
         c = (iword >> 7) & 31;  
         lastbit = 0;  
   
         if (rm == ARM_PC) {  
                 /*  Calculate tmp from this instruction's PC + 8  */  
                 uint32_t low_pc = ((size_t)ic - (size_t)  
                     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);  
                 tmp &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<  
                     ARM_INSTR_ALIGNMENT_SHIFT);  
                 tmp += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
                 tmp += 8;  
         }  
   
         if ((iword & 0xff0)==0 && rm == ARM_PC)  
                 return tmp;  
   
         if ((t & 1) && (c >> 1) == ARM_PC) {  
                 fatal("TODO: R: rc = PC\n");  
                 exit(1);  
         }  
   
         switch (t) {  
         case 0: /*  lsl #c  (c = 0..31)  */  
                 if (update_c) {  
                         if (c == 0)  
                                 update_c = 0;  
                         else  
                                 lastbit = (tmp << (c-1)) & 0x80000000;  
                 }  
                 tmp <<= c;  
                 break;  
         case 1: /*  lsl Rc  */  
                 c = cpu->cd.arm.r[c >> 1] & 255;  
                 if (c >= 32)  
                         c = 33;  
                 if (update_c) {  
                         if (c == 0)  
                                 update_c = 0;  
                         else  
                                 lastbit = ((uint64_t)tmp << (c-1)) & 0x80000000;  
                 }  
                 tmp = (uint64_t)tmp << c;  
                 break;  
         case 2: /*  lsr #c  (c = 1..32)  */  
                 if (c == 0)  
                         c = 32;  
                 if (update_c) {  
                         lastbit = ((uint64_t)tmp >> (c-1)) & 1;  
                 }  
                 tmp = (uint64_t)tmp >> c;  
                 break;  
         case 3: /*  lsr Rc  */  
                 c = cpu->cd.arm.r[c >> 1] & 255;  
                 if (c >= 32)  
                         c = 33;  
                 if (update_c) {  
                         if (c == 0)  
                                 update_c = 0;  
                         else  
                                 lastbit = ((uint64_t)tmp >> (c-1)) & 1;  
                 }  
                 tmp = (uint64_t)tmp >> c;  
                 break;  
         case 4: /*  asr #c  (c = 1..32)  */  
                 if (c == 0)  
                         c = 32;  
                 if (update_c) {  
                         lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1;  
                 }  
                 tmp = (int64_t)(int32_t)tmp >> c;  
                 break;  
         case 5: /*  asr Rc  */  
                 c = cpu->cd.arm.r[c >> 1] & 255;  
                 if (c >= 32)  
                         c = 33;  
                 if (update_c) {  
                         if (c == 0)  
                                 update_c = 0;  
                         else  
                                 lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1;  
                 }  
                 tmp = (int64_t)(int32_t)tmp >> c;  
                 break;  
         case 6: /*  ror 1..31  */  
                 if (c == 0) {  
                         fatal("TODO: rrx\n");  
                         exit(1);  
                 }  
                 if (update_c)  
                         lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1;  
                 tmp = (uint64_t)(((uint64_t)tmp << 32) | tmp) >> c;  
                 break;  
         case 7: /*  ror Rc  */  
                 c = cpu->cd.arm.r[c >> 1] & 255;  
                 if (update_c) {  
                         if (c == 0)  
                                 update_c = 0;  
                         else {  
                                 c &= 31;  
                                 if (c == 0)  
                                         lastbit = tmp & 0x80000000;  
                                 else  
                                         lastbit = ((int64_t)(int32_t)tmp  
                                             >> (c-1)) & 1;  
                                 tmp = (uint64_t)(((uint64_t)tmp << 32)  
                                     | tmp) >> c;  
                         }  
                 }  
                 break;  
         }  
         if (update_c) {  
                 cpu->cd.arm.cpsr &= ~ARM_FLAG_C;  
                 if (lastbit)  
                         cpu->cd.arm.cpsr |= ARM_FLAG_C;  
         }  
         return tmp;  
 }  
   
   
 /*****************************************************************************/  
   
136    
137  /*  /*
138   *  nop:  Do nothing.   *  nop:  Do nothing.
# Line 937  extern void (*arm_load_store_instr_3[204 Line 802  extern void (*arm_load_store_instr_3[204
802  extern void (*arm_load_store_instr_3_pc[2048])(struct cpu *,  extern void (*arm_load_store_instr_3_pc[2048])(struct cpu *,
803          struct arm_instr_call *);          struct arm_instr_call *);
804    
805    extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);
806    
807  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,
808          struct arm_instr_call *);          struct arm_instr_call *);
809  X(cmps);  X(cmps);
# Line 962  X(bdt_load) Line 829  X(bdt_load)
829          int u_bit = iw & 0x00800000;          int u_bit = iw & 0x00800000;
830          int s_bit = iw & 0x00400000;          int s_bit = iw & 0x00400000;
831          int w_bit = iw & 0x00200000;          int w_bit = iw & 0x00200000;
832          int i, return_flag = 0, saved_mode = 0;          int i, return_flag = 0;
833          uint32_t new_values[16];          uint32_t new_values[16];
834    
835          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
# Line 974  X(bdt_load) Line 841  X(bdt_load)
841          cpu->pc = cpu->cd.arm.r[ARM_PC];          cpu->pc = cpu->cd.arm.r[ARM_PC];
842    
843          if (s_bit) {          if (s_bit) {
844                  /*  Load USR registers:  */                  /*  Load to USR registers:  */
845                  if ((cpu->cd.arm.cpsr & ARM_FLAG_MODE) == ARM_MODE_USR32) {                  if ((cpu->cd.arm.cpsr & ARM_FLAG_MODE) == ARM_MODE_USR32) {
846                          fatal("[ bdt_load: s-bit: in usermode? ]\n");                          fatal("[ bdt_load: s-bit: in usermode? ]\n");
847                          s_bit = 0;                          s_bit = 0;
848                  } else if (iw & 0x8000) {                  }
849                    if (iw & 0x8000) {
850                          s_bit = 0;                          s_bit = 0;
851                          return_flag = 1;                          return_flag = 1;
                 } else {  
                         /*  Which saved mode to restore to:  */  
                         uint32_t spsr;  
                         switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {  
                         case ARM_MODE_FIQ32:  
                                 spsr = cpu->cd.arm.spsr_fiq; break;  
                         case ARM_MODE_ABT32:  
                                 spsr = cpu->cd.arm.spsr_abt; break;  
                         case ARM_MODE_UND32:  
                                 spsr = cpu->cd.arm.spsr_und; break;  
                         case ARM_MODE_IRQ32:  
                                 spsr = cpu->cd.arm.spsr_irq; break;  
                         case ARM_MODE_SVC32:  
                                 spsr = cpu->cd.arm.spsr_svc; break;  
                         default:fatal("bdt_load (1): unimplemented mode %i\n",  
                                     cpu->cd.arm.cpsr & ARM_FLAG_MODE);  
                                 exit(1);  
                         }  
                         saved_mode = spsr & ARM_FLAG_MODE;  
852                  }                  }
853          }          }
854    
# Line 1069  X(bdt_load) Line 918  X(bdt_load)
918                  if (!s_bit) {                  if (!s_bit) {
919                          cpu->cd.arm.r[i] = new_values[i];                          cpu->cd.arm.r[i] = new_values[i];
920                  } else {                  } else {
921                          switch (saved_mode) {                          switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
922                          case ARM_MODE_USR32:                          case ARM_MODE_USR32:
923                          case ARM_MODE_SYS32:                          case ARM_MODE_SYS32:
924                                  if (i >= 8 && i <= 14)                                  cpu->cd.arm.r[i] = new_values[i];
                                         cpu->cd.arm.default_r8_r14[i-8] =  
                                             new_values[i];  
                                 else  
                                         cpu->cd.arm.r[i] = new_values[i];  
925                                  break;                                  break;
926                          case ARM_MODE_FIQ32:                          case ARM_MODE_FIQ32:
927                                  if (i >= 8 && i <= 14)                                  if (i >= 8 && i <= 14)
928                                          cpu->cd.arm.fiq_r8_r14[i-8] =                                          cpu->cd.arm.default_r8_r14[i-8] =
                                             new_values[i];  
                                 else  
                                         cpu->cd.arm.r[i] = new_values[i];  
                                 break;  
                         case ARM_MODE_IRQ32:  
                                 if (i >= 13 && i <= 14)  
                                         cpu->cd.arm.irq_r13_r14[i-13] =  
929                                              new_values[i];                                              new_values[i];
930                                  else                                  else
931                                          cpu->cd.arm.r[i] = new_values[i];                                          cpu->cd.arm.r[i] = new_values[i];
932                                  break;                                  break;
933                          case ARM_MODE_SVC32:                          case ARM_MODE_SVC32:
                                 if (i >= 13 && i <= 14)  
                                         cpu->cd.arm.svc_r13_r14[i-13] =  
                                             new_values[i];  
                                 else  
                                         cpu->cd.arm.r[i] = new_values[i];  
                                 break;  
934                          case ARM_MODE_ABT32:                          case ARM_MODE_ABT32:
                                 if (i >= 13 && i <= 14)  
                                         cpu->cd.arm.abt_r13_r14[i-13] =  
                                             new_values[i];  
                                 else  
                                         cpu->cd.arm.r[i] = new_values[i];  
                                 break;  
935                          case ARM_MODE_UND32:                          case ARM_MODE_UND32:
936                            case ARM_MODE_IRQ32:
937                                  if (i >= 13 && i <= 14)                                  if (i >= 13 && i <= 14)
938                                          cpu->cd.arm.und_r13_r14[i-13] =                                          cpu->cd.arm.default_r8_r14[i-8] =
939                                              new_values[i];                                              new_values[i];
940                                  else                                  else
941                                          cpu->cd.arm.r[i] = new_values[i];                                          cpu->cd.arm.r[i] = new_values[i];
# Line 1186  X(bdt_store) Line 1013  X(bdt_store)
1013          int u_bit = iw & 0x00800000;          int u_bit = iw & 0x00800000;
1014          int s_bit = iw & 0x00400000;          int s_bit = iw & 0x00400000;
1015          int w_bit = iw & 0x00200000;          int w_bit = iw & 0x00200000;
1016          int i, saved_mode = 0;          int i;
   
         if (s_bit) {  
                 /*  Store USR (or saved) registers:  */  
                 uint32_t spsr;  
                 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {  
                 case ARM_MODE_FIQ32:  
                         spsr = cpu->cd.arm.spsr_fiq; break;  
                 case ARM_MODE_ABT32:  
                         spsr = cpu->cd.arm.spsr_abt; break;  
                 case ARM_MODE_UND32:  
                         spsr = cpu->cd.arm.spsr_und; break;  
                 case ARM_MODE_IRQ32:  
                         spsr = cpu->cd.arm.spsr_irq; break;  
                 case ARM_MODE_SVC32:  
                         spsr = cpu->cd.arm.spsr_svc; break;  
                 default:fatal("bdt_store: unimplemented mode %i\n",  
                             cpu->cd.arm.cpsr & ARM_FLAG_MODE);  
                         exit(1);  
                 }  
                 saved_mode = spsr & ARM_FLAG_MODE;  
         }  
1017    
1018          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1019          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
# Line 1226  X(bdt_store) Line 1032  X(bdt_store)
1032                  value = cpu->cd.arm.r[i];                  value = cpu->cd.arm.r[i];
1033    
1034                  if (s_bit) {                  if (s_bit) {
1035                          switch (saved_mode) {                          switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
1036                          case ARM_MODE_FIQ32:                          case ARM_MODE_FIQ32:
1037                                  if (i >= 8 && i <= 14)                                  if (i >= 8 && i <= 14)
1038                                          value = cpu->cd.arm.fiq_r8_r14[i-8];                                          value = cpu->cd.arm.default_r8_r14[i-8];
1039                                  break;                                  break;
1040                          case ARM_MODE_ABT32:                          case ARM_MODE_ABT32:
                                 if (i >= 13 && i <= 14)  
                                         value = cpu->cd.arm.abt_r13_r14[i-13];  
                                 break;  
1041                          case ARM_MODE_UND32:                          case ARM_MODE_UND32:
                                 if (i >= 13 && i <= 14)  
                                         value = cpu->cd.arm.und_r13_r14[i-13];  
                                 break;  
1042                          case ARM_MODE_IRQ32:                          case ARM_MODE_IRQ32:
                                 if (i >= 13 && i <= 14)  
                                         value = cpu->cd.arm.irq_r13_r14[i-13];  
                                 break;  
1043                          case ARM_MODE_SVC32:                          case ARM_MODE_SVC32:
1044                                  if (i >= 13 && i <= 14)                                  if (i >= 13 && i <= 14)
1045                                          value = cpu->cd.arm.svc_r13_r14[i-13];                                          value = cpu->cd.arm.default_r8_r14[i-8];
1046                                  break;                                  break;
1047                          case ARM_MODE_USR32:                          case ARM_MODE_USR32:
1048                          case ARM_MODE_SYS32:                          case ARM_MODE_SYS32:
                                 if (i >= 8 && i <= 14)  
                                         value = cpu->cd.arm.default_r8_r14[i-8];  
1049                                  break;                                  break;
1050                          }                          }
1051                  }                  }
# Line 1755  X(to_be_translated) Line 1550  X(to_be_translated)
1550                                      + (u_bit? 256 : 0) + (p_bit? 512 : 0)                                      + (u_bit? 256 : 0) + (p_bit? 512 : 0)
1551                                      + (regform? 1024 : 0)];                                      + (regform? 1024 : 0)];
1552                          if (regform)                          if (regform)
1553                                  ic->arg[1] = iword & 0xf;                                  ic->arg[1] = (size_t)(void *)arm_r[iword & 0xf];
1554                          else                          else
1555                                  ic->arg[1] = imm;                                  ic->arg[1] = imm;
1556                          break;                          break;
# Line 1790  X(to_be_translated) Line 1585  X(to_be_translated)
1585                  else                  else
1586                          regform = 0;                          regform = 0;
1587    
1588                  if (regform)                  if (regform) {
1589                          ic->arg[1] = iword;                          /*  0x1000 signifies Carry bit update on rotation,
1590                  else {                              which is not necessary for add,adc,sub,sbc,
1591                                rsb,rsc,cmp, or cmn, because they update the
1592                                Carry bit manually anyway.  */
1593                            int q = 0x1000;
1594                            if (s_bit == 0)
1595                                    q = 0;
1596                            if ((secondary_opcode >= 2 && secondary_opcode <= 7)
1597                                || secondary_opcode==0xa || secondary_opcode==0xb)
1598                                    q = 0;
1599                            ic->arg[1] = (size_t)(void *)arm_r[(iword & 0xfff) + q];
1600                    } else {
1601                          imm = iword & 0xff;                          imm = iword & 0xff;
1602                          while (r8-- > 0)                          while (r8-- > 0)
1603                                  imm = (imm >> 2) | ((imm & 3) << 30);                                  imm = (imm >> 2) | ((imm & 3) << 30);
# Line 1831  X(to_be_translated) Line 1636  X(to_be_translated)
1636                  if (main_opcode < 6)                  if (main_opcode < 6)
1637                          ic->arg[1] = imm;                          ic->arg[1] = imm;
1638                  else                  else
1639                          ic->arg[1] = iword;                          ic->arg[1] = (size_t)(void *)arm_r[iword & 0xfff];
1640                  if ((iword & 0x0e000010) == 0x06000010) {                  if ((iword & 0x0e000010) == 0x06000010) {
1641                          fatal("Not a Load/store TODO\n");                          fatal("Not a Load/store TODO\n");
1642                          goto bad;                          goto bad;

Legend:
Removed from v.15  
changed lines
  Added in v.16

  ViewVC Help
Powered by ViewVC 1.1.26