/[gxemul]/trunk/src/cpus/cpu_dyntrans.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_dyntrans.c

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

revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC revision 38 by dpavlin, Mon Oct 8 16:21:53 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.120 2006/08/12 11:43:12 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.145 2007/04/10 17:26:20 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
# Line 45  static void gather_statistics(struct cpu Line 45  static void gather_statistics(struct cpu
45          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
46              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
47    
48            if (cpu->machine->statistics_file == NULL) {
49                    fatal("statistics gathering with no filename set is"
50                        " meaningless\n");
51                    return;
52            }
53    
54          buf[0] = '\0';          buf[0] = '\0';
55    
56          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
# Line 230  int DYNTRANS_RUN_INSTR(struct cpu *cpu) Line 236  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
236          if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)          if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)
237                  ppc_exception(cpu, PPC_EXCEPTION_EI);                  ppc_exception(cpu, PPC_EXCEPTION_EI);
238  #endif  #endif
239    #ifdef DYNTRANS_SH
240            if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
241                && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
242                < cpu->cd.sh.int_level)
243                    sh_exception(cpu, 0, cpu->cd.sh.int_to_assert, 0);
244    #endif
245    
246          cached_pc = cpu->pc;          cached_pc = cpu->pc;
247    
# Line 249  int DYNTRANS_RUN_INSTR(struct cpu *cpu) Line 261  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
261                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);
262                  }                  }
263                  if (cpu->machine->instruction_trace) {                  if (cpu->machine->instruction_trace) {
264  #ifdef DYNTRANS_X86                          /*  TODO/Note: This must be large enough to hold
265                          unsigned char instr[17];                              any instruction for any ISA:  */
266                          cpu->cd.x86.cursegment = X86_S_CS;                          unsigned char instr[1 <<
267                          cpu->cd.x86.seg_override = 0;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT];
 #else  
 #ifdef DYNTRANS_M68K  
                         unsigned char instr[16];        /*  TODO: 16?  */  
 #else  
                         unsigned char instr[4];         /*  General case...  */  
 #endif  
 #endif  
   
268                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
269                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
270                                  fatal("XXX_run_instr(): could not read "                                  fatal("XXX_run_instr(): could not read "
271                                      "the instruction\n");                                      "the instruction\n");
272                          } else {                          } else {
273                                  cpu_disassemble_instr(cpu->machine, cpu,  #ifdef DYNTRANS_DELAYSLOT
274                                      instr, 1, 0);                                  int len =
275    #endif
276                                        cpu_disassemble_instr(
277                                        cpu->machine, cpu, instr, 1, 0);
278  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
279                                  /*  Show the instruction in the delay slot,                                  /*  Show the instruction in the delay slot,
280                                      if any:  */                                      if any:  */
# Line 278  int DYNTRANS_RUN_INSTR(struct cpu *cpu) Line 285  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
285                                      instr)) {                                      instr)) {
286                                          int saved_delayslot = cpu->delay_slot;                                          int saved_delayslot = cpu->delay_slot;
287                                          cpu->memory_rw(cpu, cpu->mem, cached_pc                                          cpu->memory_rw(cpu, cpu->mem, cached_pc
288                                              + sizeof(instr), &instr[0],                                              + len, &instr[0],
289                                              sizeof(instr), MEM_READ,                                              sizeof(instr), MEM_READ,
290                                              CACHE_INSTRUCTION);                                              CACHE_INSTRUCTION);
291                                          cpu->delay_slot = DELAYED;                                          cpu->delay_slot = DELAYED;
292                                          cpu->pc += sizeof(instr);                                          cpu->pc += len;
293                                          cpu_disassemble_instr(cpu->machine,                                          cpu_disassemble_instr(cpu->machine,
294                                              cpu, instr, 1, 0);                                              cpu, instr, 1, 0);
295                                          cpu->delay_slot = saved_delayslot;                                          cpu->delay_slot = saved_delayslot;
296                                          cpu->pc -= sizeof(instr);                                          cpu->pc -= len;
297                                  }                                  }
298  #endif  #endif
299                          }                          }
# Line 339  while (cycles-- > 0) Line 346  while (cycles-- > 0)
346                  }                  }
347          } else {          } else {
348                  /*  Execute multiple instructions:  */                  /*  Execute multiple instructions:  */
349                  int n = 0;                  n_instrs = 0;
350                  for (;;) {                  for (;;) {
351                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
352    
# Line 351  while (cycles-- > 0) Line 358  while (cycles-- > 0)
358    
359                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
360    
361                          n += 60;                          I; I; I; I; I;   I; I; I; I; I;
362                            I; I; I; I; I;   I; I; I; I; I;
363                            I; I; I; I; I;   I; I; I; I; I;
364                            I; I; I; I; I;   I; I; I; I; I;
365                            I; I; I; I; I;   I; I; I; I; I;
366    
367                          if (n + cpu->n_translated_instrs >=                          I; I; I; I; I;   I; I; I; I; I;
368                              N_SAFE_DYNTRANS_LIMIT)  
369                            cpu->n_translated_instrs += 120;
370                            if (cpu->n_translated_instrs >= N_SAFE_DYNTRANS_LIMIT)
371                                  break;                                  break;
372                  }                  }
                 n_instrs = n;  
373          }          }
374    
375          n_instrs += cpu->n_translated_instrs;          n_instrs += cpu->n_translated_instrs;
# Line 394  while (cycles-- > 0) Line 406  while (cycles-- > 0)
406                      (int32_t) (old + n_instrs);                      (int32_t) (old + n_instrs);
407                  diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -                  diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
408                      cpu->cd.mips.coproc[0]->reg[COP0_COUNT];                      cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
409                  if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0)  
410                          cpu_interrupt(cpu, 7);                  if (cpu->cd.mips.compare_register_set) {
411    #if 1
412    /*  Not yet.  TODO  */
413                            if (cpu->machine->emulated_hz > 0) {
414                                    if (cpu->cd.mips.compare_interrupts_pending > 0)
415                                            INTERRUPT_ASSERT(
416                                                cpu->cd.mips.irq_compare);
417                            } else
418    #endif
419                            {
420                                    if (diff1 > 0 && diff2 <= 0)
421                                            INTERRUPT_ASSERT(
422                                                cpu->cd.mips.irq_compare);
423                            }
424                    }
425          }          }
426  #endif  #endif
427  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
# Line 438  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 464  void DYNTRANS_FUNCTION_TRACE(struct cpu
464              6              6
465  #else  #else
466  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
467              8              8   /*  Both for 32-bit and 64-bit SuperH  */
468  #else  #else
469              4   /*  Default value for most archs  */              4   /*  Default value for most archs  */
470  #endif  #endif
# Line 462  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 488  void DYNTRANS_FUNCTION_TRACE(struct cpu
488           *  than were passed in register.           *  than were passed in register.
489           */           */
490          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
491                  int64_t d;                  int64_t d = cpu->cd.DYNTRANS_ARCH.
 #if defined(DYNTRANS_X86) || defined(DYNTRANS_TRANSPUTER)  
                 d = 0;          /*  TODO  */  
 #else  
                 /*  Args in registers:  */  
                 d = cpu->cd.DYNTRANS_ARCH.  
492  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
493                      r[ALPHA_A0                      r[ALPHA_A0
494  #endif  #endif
# Line 479  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 500  void DYNTRANS_FUNCTION_TRACE(struct cpu
500                          they go downwards, ie. 22,23 and so on  */                          they go downwards, ie. 22,23 and so on  */
501                      r[24                      r[24
502  #endif  #endif
 #ifdef DYNTRANS_HPPA  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_I960  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_IA64  
                     r[0         /*  TODO  */  
 #endif  
503  #ifdef DYNTRANS_M68K  #ifdef DYNTRANS_M68K
504                      d[0         /*  TODO  */                      d[0         /*  TODO  */
505  #endif  #endif
# Line 498  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 510  void DYNTRANS_FUNCTION_TRACE(struct cpu
510                      gpr[3                      gpr[3
511  #endif  #endif
512  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
513                      r[2                      r[4         /*  NetBSD seems to use 4? But 2 seems
514                                            to be used by other code? TODO  */
515  #endif  #endif
516  #ifdef DYNTRANS_SPARC  #ifdef DYNTRANS_SPARC
517                      r[24                      r[8         /*  o0..o5  */
518  #endif  #endif
519                      + x];                      + x];
520  #endif  
521                  symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);                  symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);
522    
523                  if (d > -256 && d < 256)                  if (d > -256 && d < 256)
# Line 655  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 668  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
668                          }                          }
669  #else  #else
670                          x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;                          x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
671                          x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;                          x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N))
672                          x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))                              & mask2;
673                              & mask3;                          x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N
674                                - DYNTRANS_L3N)) & mask3;
675                          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];                          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
676                          l3 = l2->l3[x2];                          l3 = l2->l3[x2];
677                          if (l3->host_load[x3] != NULL) {                          if (l3->host_load[x3] != NULL) {
# Line 701  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 715  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
715                  }                  }
716          }          }
717    
718          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= dyntrans_cache_size) {
719  #ifdef UNSTABLE_DEVEL  #ifdef UNSTABLE_DEVEL
720                  fatal("[ dyntrans: resetting the translation cache ]\n");                  fatal("[ dyntrans: resetting the translation cache ]\n");
721  #endif  #endif
# Line 728  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 742  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
742                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
743          }          }
744    
745          /*  If the offset is 0 (or ppp is NULL), then we need to create a          /*
746              new "default" empty translation page.  */           *  If the offset is 0, then no translation exists yet for this
747             *  physical address. Let's create a new page, and add it first in
748             *  the chain.
749             */
750            if (physpage_ofs == 0) {
751                    uint32_t previous_first_page_in_chain;
752    
         if (ppp == NULL) {  
753                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
754                      "index %i\n", (long long)pagenr, (uint64_t)physaddr,                      "index %i\n", (long long)pagenr, (uint64_t)physaddr,
755                      (int)table_index);  */                      (int)table_index);  */
756    
757                    previous_first_page_in_chain = *physpage_entryp;
758    
759                    /*  Insert the new page first in the chain:  */
760                  *physpage_entryp = physpage_ofs =                  *physpage_entryp = physpage_ofs =
761                      cpu->translation_cache_cur_ofs;                      cpu->translation_cache_cur_ofs;
762    
# Line 743  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 765  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
765    
766                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
767                      + physpage_ofs);                      + physpage_ofs);
768    
769                    /*  Point to the other pages in the same chain:  */
770                    ppp->next_ofs = previous_first_page_in_chain;
771          }          }
772    
773            /*  Here, ppp points to a valid physical page struct.  */
774    
775  #ifdef MODE32  #ifdef MODE32
776          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
777                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
# Line 1224  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1251  void DYNTRANS_INVALIDATE_TC_CODE(struct
1251                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
1252                      translation_cache)[table_index]);                      translation_cache)[table_index]);
1253                  physpage_ofs = *physpage_entryp;                  physpage_ofs = *physpage_entryp;
1254    
1255                    /*  Return immediately if there is no code translation
1256                        for this page.  */
1257                    if (physpage_ofs == 0)
1258                            return;
1259    
1260                  prev_ppp = ppp = NULL;                  prev_ppp = ppp = NULL;
1261    
1262                  /*  Traverse the physical page chain:  */                  /*  Traverse the physical page chain:  */
# Line 1241  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1274  void DYNTRANS_INVALIDATE_TC_CODE(struct
1274                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1275                  }                  }
1276    
1277                    /*  If there is no translation, there is no need to go
1278                        on and try to remove it from the vph_tlb_entry array:  */
1279                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1280                          ppp = NULL;                          return;
1281    
1282  #if 0  #if 0
1283                  /*                  /*
# Line 1341  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1376  void DYNTRANS_INVALIDATE_TC_CODE(struct
1376  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1377          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1378  {  {
1379          int found, r, lowest_index, useraccess = 0;          int found, r, useraccess = 0;
1380    
1381  #ifdef MODE32  #ifdef MODE32
1382          uint32_t index;          uint32_t index;
# Line 1372  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1407  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1407          }          }
1408    
1409          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
         lowest_index = 0;  
1410    
1411  #ifdef MODE32  #ifdef MODE32
1412          /*          /*
# Line 1404  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1438  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1438  #endif  #endif
1439    
1440          if (found < 0) {          if (found < 0) {
1441                    /*  Create the new TLB entry, overwriting a "random" entry:  */
1442                  static unsigned int x = 0;                  static unsigned int x = 0;
1443                  lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;                  r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
         }  
1444    
         if (found < 0) {  
                 /*  Create the new TLB entry, overwriting the oldest one:  */  
                 r = lowest_index;  
1445                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1446                          /*  This one has to be invalidated first:  */                          /*  This one has to be invalidated first:  */
1447                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,

Legend:
Removed from v.30  
changed lines
  Added in v.38

  ViewVC Help
Powered by ViewVC 1.1.26