/[dynamips]/upstream/dynamips-0.2.7-RC3/ppc32_jit.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 /upstream/dynamips-0.2.7-RC3/ppc32_jit.c

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

upstream/dynamips-0.2.7-RC2/ppc32_jit.c revision 8 by dpavlin, Sat Oct 6 16:24:54 2007 UTC upstream/dynamips-0.2.7-RC3/ppc32_jit.c revision 9 by dpavlin, Sat Oct 6 16:26:06 2007 UTC
# Line 239  static forced_inline ppc_insn_t insn_fet Line 239  static forced_inline ppc_insn_t insn_fet
239     return(vmtoh32(b->ppc_code[b->ppc_trans_pos]));     return(vmtoh32(b->ppc_code[b->ppc_trans_pos]));
240  }  }
241    
242    #define DEBUG_HREG  0
243    
244    /* Show register allocation status */
245    static void ppc32_jit_show_hreg_status(cpu_ppc_t *cpu)
246    {    
247       struct hreg_map *map;
248    
249       printf("PPC32-JIT: reg status for insn '%s'\n",cpu->jit_hreg_seq_name);
250    
251       for(map=cpu->hreg_map_list;map;map=map->next) {
252          switch(map->flags) {
253             case 0:
254                printf("   hreg %d is free, mapped to vreg %d\n",
255                       map->hreg,map->vreg);
256                break;
257             case HREG_FLAG_ALLOC_LOCKED:
258                printf("   hreg %d is locked, mapped to vreg %d\n",
259                       map->hreg,map->vreg);
260                break;
261             case HREG_FLAG_ALLOC_FORCED:
262                printf("   hreg %d is in forced alloc\n",map->hreg);
263                break;
264          }
265       }
266    }
267    
268    /* Extract an host reg mapping from the register list */
269    static void ppc32_jit_extract_hreg(cpu_ppc_t *cpu,struct hreg_map *map)
270    {
271       if (map->prev != NULL)
272          map->prev->next = map->next;
273       else
274          cpu->hreg_map_list = map->next;
275    
276       if (map->next != NULL)
277          map->next->prev = map->prev;
278       else
279          cpu->hreg_lru = map->prev;
280    }
281    
282    /* Insert a reg map as head of list (as MRU element) */
283    void ppc32_jit_insert_hreg_mru(cpu_ppc_t *cpu,struct hreg_map *map)
284    {
285       map->next = cpu->hreg_map_list;
286       map->prev = NULL;
287    
288       if (map->next == NULL) {
289          cpu->hreg_lru = map;
290       } else {
291          map->next->prev = map;
292       }
293    
294       cpu->hreg_map_list = map;
295    }
296    
297    /* Start register allocation sequence */
298    void ppc32_jit_start_hreg_seq(cpu_ppc_t *cpu,char *insn)
299    {
300       struct hreg_map *map;
301    
302    #if DEBUG_HREG
303       printf("Starting hreg_seq insn='%s'\n",insn);
304    #endif
305    
306       /* Reset the allocation state of all host registers */
307       for(map=cpu->hreg_map_list;map;map=map->next)
308          map->flags = 0;
309    
310       /* Save the instruction name for debugging/error analysis */
311       cpu->jit_hreg_seq_name = insn;
312    }
313    
314    /* Close register allocation sequence */
315    void ppc32_jit_close_hreg_seq(cpu_ppc_t *cpu)
316    {
317    #if DEBUG_HREG
318       ppc32_show_hreg_status(cpu);
319    #endif
320    }
321    
322    /* Find a free host register to use */
323    static struct hreg_map *ppc32_jit_get_free_hreg(cpu_ppc_t *cpu)
324    {
325       struct hreg_map *map,*oldest_free = NULL;
326    
327       for(map=cpu->hreg_lru;map;map=map->prev) {
328          if ((map->vreg == -1) && (map->flags == 0))
329             return map;
330    
331          if ((map->flags == 0) && !oldest_free)
332             oldest_free = map;
333       }
334    
335       if (!oldest_free) {
336          fprintf(stderr,
337                  "ppc32_get_free_hreg: unable to find free reg for insn %s\n",
338                  cpu->jit_hreg_seq_name);
339       }
340    
341       return oldest_free;
342    }
343    
344    /* Allocate an host register */
345    int ppc32_jit_alloc_hreg(cpu_ppc_t *cpu,int ppc_reg)
346    {
347       struct hreg_map *map;
348       int hreg;
349    
350       /*
351        * If PPC reg is invalid, the caller requested for a temporary register.
352        */
353       if (ppc_reg == -1) {
354          if ((map = ppc32_jit_get_free_hreg(cpu)) == NULL)
355             return(-1);
356    
357          /* Allocate the register and invalidate its PPC mapping if present */
358          map->flags = HREG_FLAG_ALLOC_LOCKED;
359    
360          if (map->vreg != -1) {
361             cpu->ppc_reg_map[map->vreg] = -1;
362             map->vreg = -1;
363          }
364    
365          return(map->hreg);
366       }
367    
368       hreg = cpu->ppc_reg_map[ppc_reg];
369    
370       /*
371        * If the PPC register is already mapped to an host register, re-use this
372        * mapping and put this as MRU mapping.
373        */
374       if (hreg != -1) {
375          map = &cpu->hreg_map[hreg];
376       } else {
377          /*
378           * This PPC register has no mapping to host register. Find a free
379           * register.
380           */
381          if ((map = ppc32_jit_get_free_hreg(cpu)) == NULL)
382             return(-1);
383    
384          /* Remove the old PPC mapping if present */
385          if (map->vreg != -1)
386             cpu->ppc_reg_map[map->vreg] = -1;
387          
388          /* Establish the new mapping */
389          cpu->ppc_reg_map[ppc_reg] = map->hreg;
390          map->vreg = ppc_reg;
391       }
392    
393       /* Prevent this register from further allocation in this instruction */
394       map->flags = HREG_FLAG_ALLOC_LOCKED;
395       ppc32_jit_extract_hreg(cpu,map);
396       ppc32_jit_insert_hreg_mru(cpu,map);
397       return(map->hreg);
398    }
399    
400    /* Force allocation of an host register */
401    int ppc32_jit_alloc_hreg_forced(cpu_ppc_t *cpu,int hreg)
402    {
403       int ppc_reg;
404    
405       ppc_reg = cpu->hreg_map[hreg].vreg;
406    
407       /* Check that this register is not already allocated */
408       if (cpu->hreg_map[hreg].flags != 0) {
409          fprintf(stderr,"ppc32_alloc_hreg_forced: trying to force allocation "
410                  "of hreg %d (insn %s)\n",
411                  hreg,cpu->jit_hreg_seq_name);
412          return(-1);
413       }
414    
415       cpu->hreg_map[hreg].flags = HREG_FLAG_ALLOC_FORCED;
416       cpu->hreg_map[hreg].vreg  = -1;
417    
418       if (ppc_reg != -1)
419          cpu->ppc_reg_map[ppc_reg] = -1;
420    
421       return(0);
422    }
423    
424  /* Emit a breakpoint if necessary */  /* Emit a breakpoint if necessary */
425  #if BREAKPOINT_ENABLE  #if BREAKPOINT_ENABLE
426  static void insn_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)  static void insn_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
# Line 250  static void insn_emit_breakpoint(cpu_ppc Line 432  static void insn_emit_breakpoint(cpu_ppc
432    
433     for(i=0;i<PPC32_MAX_BREAKPOINTS;i++)     for(i=0;i<PPC32_MAX_BREAKPOINTS;i++)
434        if (ia == cpu->breakpoints[i]) {        if (ia == cpu->breakpoints[i]) {
435           ppc32_emit_breakpoint(b);           ppc32_emit_breakpoint(cpu,b);
436           break;           break;
437        }        }
438  }  }
# Line 266  struct ppc32_insn_tag *ppc32_jit_fetch_a Line 448  struct ppc32_insn_tag *ppc32_jit_fetch_a
448     code = insn_fetch(block);     code = insn_fetch(block);
449     tag = insn_tag_find(code);     tag = insn_tag_find(code);
450     assert(tag);     assert(tag);
     
    block->jit_insn_ptr[block->ppc_trans_pos] = block->jit_ptr;  
    block->ppc_trans_pos++;  
   
 #if DEBUG_INSN_PERF_CNT  
    ppc32_inc_perf_counter(block);  
 #endif  
   
 #if BREAKPOINT_ENABLE  
    if (cpu->breakpoints_enabled)  
       insn_emit_breakpoint(cpu,block);  
 #endif  
451    
452     tag->emit(cpu,block,code);     tag->emit(cpu,block,code);
453     return tag;     return tag;
# Line 286  struct ppc32_insn_tag *ppc32_jit_fetch_a Line 456  struct ppc32_insn_tag *ppc32_jit_fetch_a
456  /* Add end of JIT block */  /* Add end of JIT block */
457  static void ppc32_jit_tcb_add_end(ppc32_jit_tcb_t *b)  static void ppc32_jit_tcb_add_end(ppc32_jit_tcb_t *b)
458  {  {
459     ppc32_set_ia(b,b->start_ia+(b->ppc_trans_pos<<2));     ppc32_set_ia(&b->jit_ptr,b->start_ia+(b->ppc_trans_pos<<2));
460     ppc32_jit_tcb_push_epilog(b);     ppc32_jit_tcb_push_epilog(&b->jit_ptr);
461  }  }
462    
463  /* Record a patch to apply in a compiled block */  /* Record a patch to apply in a compiled block */
464  int ppc32_jit_tcb_record_patch(ppc32_jit_tcb_t *block,u_char *jit_ptr,  int ppc32_jit_tcb_record_patch(ppc32_jit_tcb_t *block,jit_op_t *iop,
465                                 m_uint32_t vaddr)                                 u_char *jit_ptr,m_uint32_t vaddr)
466  {  {
467     struct ppc32_jit_patch_table *ipt = block->patch_table;     struct ppc32_jit_patch_table *ipt = block->patch_table;
468     struct ppc32_insn_patch *patch;     struct ppc32_insn_patch *patch;
469    
470     /* pc must be 32-bit aligned */     /* pc must be 32-bit aligned */
471     if (vaddr & 0x03) {     if (vaddr & 0x03) {
472        fprintf(stderr,"Block 0x%8.8x: trying to record an invalid IA "        fprintf(stderr,
473                "(0x%8.8x) - ppc_trans_pos=%d.\n",                "Block 0x%8.8x: trying to record an invalid IA (0x%8.8x)\n",
474                block->start_ia,vaddr,block->ppc_trans_pos);                block->start_ia,vaddr);
475        return(-1);        return(-1);
476     }     }
477    
# Line 328  int ppc32_jit_tcb_record_patch(ppc32_jit Line 498  int ppc32_jit_tcb_record_patch(ppc32_jit
498     patch = &ipt->patches[ipt->cur_patch];     patch = &ipt->patches[ipt->cur_patch];
499     patch->jit_insn = jit_ptr;     patch->jit_insn = jit_ptr;
500     patch->ppc_ia = vaddr;     patch->ppc_ia = vaddr;
501     ipt->cur_patch++;       ipt->cur_patch++;
502    
503       patch->next = iop->arg_ptr;
504       iop->arg_ptr = patch;
505     return(0);     return(0);
506  }  }
507    
508  /* Apply all patches */  /* Apply patches for a JIT instruction block */
509  static int ppc32_jit_tcb_apply_patches(cpu_ppc_t *cpu,  static int ppc32_jit_tcb_apply_patches(cpu_ppc_t *cpu,
510                                          ppc32_jit_tcb_t *block)                                         ppc32_jit_tcb_t *block,
511                                           jit_op_t *iop)
512  {  {
    struct ppc32_jit_patch_table *ipt;  
513     struct ppc32_insn_patch *patch;     struct ppc32_insn_patch *patch;
514     u_char *jit_dst;     u_char *jit_ptr,*jit_dst;
515     int i;     u_int pos;
516    
517     for(ipt=block->patch_table;ipt;ipt=ipt->next)     for(patch=iop->arg_ptr;patch;patch=patch->next) {
518        for(i=0;i<ipt->cur_patch;i++)        jit_ptr = (patch->jit_insn - iop->ob_data) + iop->ob_final;
       {  
          patch = &ipt->patches[i];  
          jit_dst = ppc32_jit_tcb_get_host_ptr(block,patch->ppc_ia);  
519    
520           if (jit_dst) {        pos = (patch->ppc_ia & PPC32_MIN_PAGE_IMASK) >> 2;
521  #if DEBUG_BLOCK_PATCH        jit_dst = block->jit_insn_ptr[pos];
522              printf("Block 0x%8.8x: applying patch "  
523                     "[JIT:%p->ppc:0x%8.8x=JIT:%p]\n",        if (jit_dst) {
524                     block->start_ia,patch->jit_insn,patch->ppc_ia,jit_dst);  #if DEBUG_BLOCK_PATCH      
525             printf("Block 0x%8.8x: applying patch "
526                    "[JIT:%p->ppc:0x%8.8x=JIT:%p, ]\n",
527                    block->start_ia,patch->jit_insn,patch->ppc_ia,jit_dst);
528  #endif  #endif
529              ppc32_jit_tcb_set_patch(patch->jit_insn,jit_dst);           ppc32_jit_tcb_set_patch(jit_ptr,jit_dst);
530           }        } else {
531             printf("Block 0x%8.8x: null dst for patch!\n",block->start_ia);
532        }        }
533       }
534      
535     return(0);     return(0);
536  }  }
537    
# Line 420  static inline ppc32_jit_tcb_t *ppc32_jit Line 595  static inline ppc32_jit_tcb_t *ppc32_jit
595     return p;     return p;
596  }  }
597    
598  /* Free an instruction block */  /* Free the code chunks */
599  void ppc32_jit_tcb_free(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block,  static void
600                           int list_removal)  ppc32_jit_tcb_free_code_chunks(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
601  {  {
602     int i;     int i;
603    
604       /* Free code pages */
605       for(i=0;i<PPC_JIT_MAX_CHUNKS;i++) {
606          exec_page_free(cpu,block->jit_chunks[i]);
607          block->jit_chunks[i] = NULL;
608       }
609    
610       /* Free the current JIT buffer */
611       exec_page_free(cpu,block->jit_buffer);
612       block->jit_buffer = NULL;
613    }
614    
615    /* Free an instruction block */
616    void ppc32_jit_tcb_free(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block,
617                            int list_removal)
618    {
619     if (block) {     if (block) {
620        if (list_removal) {        if (list_removal) {
621           /* Remove the block from the linked list */           /* Remove the block from the linked list */
# Line 455  void ppc32_jit_tcb_free(cpu_ppc_t *cpu,p Line 645  void ppc32_jit_tcb_free(cpu_ppc_t *cpu,p
645        ppc32_jit_tcb_free_patches(block);        ppc32_jit_tcb_free_patches(block);
646    
647        /* Free code pages */        /* Free code pages */
648        for(i=0;i<PPC_JIT_MAX_CHUNKS;i++)        ppc32_jit_tcb_free_code_chunks(cpu,block);
          exec_page_free(cpu,block->jit_chunks[i]);  
   
       /* Free the current JIT buffer */  
       exec_page_free(cpu,block->jit_buffer);  
649    
650        /* Free the PowerPC-to-native code mapping */        /* Free the PowerPC-to-native code mapping */
651        free(block->jit_insn_ptr);        free(block->jit_insn_ptr);
# Line 512  static ppc32_jit_tcb_t *ppc32_jit_tcb_cr Line 698  static ppc32_jit_tcb_t *ppc32_jit_tcb_cr
698     return NULL;     return NULL;
699  }  }
700    
701    /* ======================================================================== */
702    
703    /* Dump a JIT opcode */
704    static void ppc32_op_dump_opcode(jit_op_t *op)
705    {
706       switch(op->opcode) {
707          case JIT_OP_BRANCH_TARGET:
708             printf("branch_target");
709             break;
710          case JIT_OP_BRANCH_JUMP:
711             printf("branch_jump");
712             break;
713          case JIT_OP_EOB:
714             printf("eob");
715             break;
716          case JIT_OP_LOAD_GPR:
717             printf("load_gpr(%d,$%d,r:%d)",
718                    op->param[0],op->param[1],op->param[2]);
719             break;
720          case JIT_OP_STORE_GPR:
721             printf("store_gpr(%d,$%d,r:%d)",
722                    op->param[0],op->param[1],op->param[2]);
723             break;
724          case JIT_OP_ALTER_HOST_REG:
725             printf("alter_host_reg(%d)",op->param[0]);
726             break;
727          case JIT_OP_UPDATE_FLAGS:
728             printf("update_flags(%d,%s)",
729                    op->param[0],(op->param[1] ? "signed" : "unsigned"));
730             break;
731          case JIT_OP_REQUIRE_FLAGS:
732             printf("require_flags(%d)",op->param[0]);
733             break;
734          case JIT_OP_TRASH_FLAGS:
735             printf("trash_flags(%d)",op->param[0]);
736             break;
737          case JIT_OP_INSN_OUTPUT:
738             printf("insn_out(\"%s\")",op->insn_name);
739             break;
740          case JIT_OP_SET_HOST_REG_IMM32:
741             printf("set_host_reg_imm32(%d,0x%8.8x)",op->param[0],op->param[1]);
742             break;
743          default:
744             printf("op(%u)",op->opcode);
745       }
746    }
747    
748    /* Dump JIT operations (debugging) */
749    static void ppc32_op_dump(cpu_gen_t *cpu,ppc32_jit_tcb_t *b)
750    {
751       m_uint32_t ia = b->start_ia;
752       jit_op_t *op;
753       int i;
754    
755       printf("PPC32-JIT: dump of page 0x%8.8x\n",ia);
756    
757       for(i=0;i<PPC32_INSN_PER_PAGE;i++,ia+=sizeof(ppc_insn_t)) {
758          printf("  0x%8.8x: ", ia);
759    
760          for(op=cpu->jit_op_array[i];op;op=op->next) {
761             ppc32_op_dump_opcode(op);
762             printf(" ");
763          }
764    
765          printf("\n");
766       }
767    
768       printf("\n");
769    }
770    
771    /* PPC register mapping */
772    typedef struct {
773       int host_reg;
774       jit_op_t *last_store;
775       m_uint32_t last_store_ia;
776    }ppc_reg_map_t;
777    
778    /* Clear register mapping (with PPC register) */
779    static void ppc32_clear_ppc_reg_map(ppc_reg_map_t *ppc_map,int *host_map,
780                                        int reg)
781    {
782       int i,hreg;
783    
784       if (reg == JIT_OP_ALL_REGS) {
785          for(i=0;i<PPC32_GPR_NR;i++) {
786             ppc_map[i].host_reg = JIT_OP_INV_REG;
787             ppc_map[i].last_store = NULL;
788          }
789    
790          for(i=0;i<JIT_HOST_NREG;i++)
791             host_map[i] = JIT_OP_INV_REG;
792       } else {
793          hreg = ppc_map[reg].host_reg;
794    
795          if (hreg != JIT_OP_INV_REG)
796             host_map[hreg] = JIT_OP_INV_REG;
797          
798          ppc_map[reg].host_reg = JIT_OP_INV_REG;
799          ppc_map[reg].last_store = NULL;
800       }
801    }
802    
803    /* Clear register mapping (with host register) */
804    static void ppc32_clear_host_reg_map(ppc_reg_map_t *ppc_map,int *host_map,
805                                         int reg)
806    {
807       int ppc_reg;
808    
809       if (host_map[reg] != JIT_OP_INV_REG) {
810          ppc_reg = host_map[reg];
811    
812          ppc_map[ppc_reg].host_reg = JIT_OP_INV_REG;
813          ppc_map[ppc_reg].last_store = NULL;
814          host_map[reg] = JIT_OP_INV_REG;
815       }
816    }
817    
818    /* Dump register mapping */
819    static void ppc32_dump_reg_map(ppc_reg_map_t *map_array,int *host_map)
820    {
821       int i;
822    
823       printf("PPC32-JIT: current register mapping:\n");
824    
825       for(i=0;i<PPC32_GPR_NR;i++)
826          printf("  ppc reg %2.2d: %d\n",i,map_array[i].host_reg);
827    
828       printf("\n");
829    
830       for(i=0;i<JIT_HOST_NREG;i++)
831          printf("  hreg %d: %d\n",i,host_map[i]);
832    
833       printf("\n");
834    }
835    
836    /* Check register mapping consistency */
837    static int ppc32_check_reg_map(ppc_reg_map_t *map_array,int *host_map)
838    {
839       ppc_reg_map_t *map;
840       int i;
841    
842       for(i=0;i<PPC32_GPR_NR;i++) {
843          map = &map_array[i];
844    
845          if ((map->host_reg != JIT_OP_INV_REG) && (host_map[map->host_reg] != i))
846             goto error;
847       }
848    
849       for(i=0;i<JIT_HOST_NREG;i++) {
850          if ((host_map[i] != JIT_OP_INV_REG) &&
851              (map_array[host_map[i]].host_reg != i))
852             goto error;
853       }
854    
855       return(0);
856    
857     error:
858       printf("PPC32_JIT: inconsistency in register mapping.\n");
859       ppc32_dump_reg_map(map_array,host_map);
860       exit(1);
861    }
862    
863    /* Optimize JIT operations */
864    static void ppc32_op_optimize(cpu_gen_t *cpu,ppc32_jit_tcb_t *b)
865    {
866       ppc_reg_map_t ppc_map[PPC32_GPR_NR],*map;
867       int reg,host_map[JIT_HOST_NREG];
868       jit_op_t *op,*opx,*last_cr_update[8];
869       m_uint32_t cur_ia;
870       int i,j;
871    
872       ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);
873    
874       for(i=0;i<8;i++)
875          last_cr_update[i] = NULL;
876    
877       for(i=0;i<PPC32_INSN_PER_PAGE;i++) {
878          for(op=cpu->jit_op_array[i];op;op=op->next)
879          {
880             //ppc32_check_reg_map(ppc_map,host_map);
881             cur_ia = b->start_ia + (i << 2);
882    
883             switch(op->opcode) {
884                /* Clear mapping if end of block or branch target */
885                case JIT_OP_BRANCH_TARGET:
886                case JIT_OP_EOB:
887                   ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);
888    
889                   for(j=0;j<8;j++)
890                      last_cr_update[j] = NULL;
891                   break;
892    
893                /* Branch jump: clear "store" operation status */
894                case JIT_OP_BRANCH_JUMP:
895                   for(j=0;j<PPC32_GPR_NR;j++)
896                      ppc_map[j].last_store = NULL;
897    
898                   for(j=0;j<8;j++)
899                      last_cr_update[j] = NULL;
900                   break;
901    
902                /* Alteration of a specific host register */
903                case JIT_OP_ALTER_HOST_REG:
904                   reg = op->param[0];
905    
906                   if (reg != JIT_OP_ALL_REGS) {
907                      if (host_map[reg] != JIT_OP_INV_REG)
908                         ppc32_clear_ppc_reg_map(ppc_map,host_map,host_map[reg]);
909                   } else {
910                      ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);
911                   }
912                   break;
913    
914                /* Save reg mapping and last operation */
915                case JIT_OP_STORE_GPR:
916                   reg = op->param[0];
917                   map = &ppc_map[op->param[1]];
918    
919                   /* clear old mapping */
920                   if (reg != map->host_reg) {
921                      ppc32_clear_host_reg_map(ppc_map,host_map,reg);
922                      ppc32_clear_ppc_reg_map(ppc_map,host_map,op->param[1]);
923                   }
924                  
925                   /* cancel previous store op for this PPC register */
926                   if (map->last_store) {
927                      map->last_store->param[0] = JIT_OP_INV_REG;
928                      map->last_store = NULL;
929                   }
930    
931                   map->host_reg = reg;
932                   map->last_store = op;
933                   map->last_store_ia = cur_ia;
934                   host_map[reg] = op->param[1];
935                   break;
936    
937                /* Load reg: check if can avoid it */
938                case JIT_OP_LOAD_GPR:
939                   reg = op->param[0];
940                   map = &ppc_map[op->param[1]];
941    
942                   if (reg == map->host_reg) {
943                      /* Cancel this load */
944                      op->param[0] = JIT_OP_INV_REG;
945                   } else {
946                      /* clear old mapping */
947                      ppc32_clear_host_reg_map(ppc_map,host_map,reg);
948                      ppc32_clear_ppc_reg_map(ppc_map,host_map,op->param[1]);
949    
950                      /* Save this reg mapping */
951                      map->host_reg = op->param[0];
952                      map->last_store = NULL;
953                      host_map[op->param[0]] = op->param[1];
954                   }
955                   break;
956    
957                /* Trash flags */
958                case JIT_OP_TRASH_FLAGS:
959                   for(j=0;j<8;j++)
960                      last_cr_update[j] = NULL;
961                   break;
962    
963                /* Flags required */
964                case JIT_OP_REQUIRE_FLAGS:
965                   if (op->param[0] != JIT_OP_PPC_ALL_FLAGS) {
966                      last_cr_update[op->param[0]] = NULL;
967                   } else {
968                      for(j=0;j<8;j++)
969                         last_cr_update[j] = NULL;
970                   }
971                   break;
972    
973                /* Update flags */
974                case JIT_OP_UPDATE_FLAGS:
975                   opx = last_cr_update[op->param[0]];
976    
977                   if (opx != NULL)
978                      opx->param[0] = JIT_OP_INV_REG;
979    
980                   last_cr_update[op->param[0]] = op;
981                   break;
982             }
983          }
984       }
985    }
986    
987    /* Generate the JIT code for the specified JIT op list */
988    static void ppc32_op_gen_list(ppc32_jit_tcb_t *b,int ipos,jit_op_t *op_list,
989                                  u_char *jit_start)
990    {
991       jit_op_t *op;
992    
993       for(op=op_list;op;op=op->next) {
994          switch(op->opcode) {
995             case JIT_OP_INSN_OUTPUT:
996                ppc32_op_insn_output(b,op);
997                break;
998             case JIT_OP_LOAD_GPR:
999                ppc32_op_load_gpr(b,op);
1000                break;
1001             case JIT_OP_STORE_GPR:
1002                ppc32_op_store_gpr(b,op);
1003                break;
1004             case JIT_OP_UPDATE_FLAGS:
1005                ppc32_op_update_flags(b,op);
1006                break;
1007             case JIT_OP_BRANCH_TARGET:
1008                b->jit_insn_ptr[ipos] = jit_start;
1009                break;
1010             case JIT_OP_MOVE_HOST_REG:
1011                ppc32_op_move_host_reg(b,op);
1012                break;
1013             case JIT_OP_SET_HOST_REG_IMM32:
1014                ppc32_op_set_host_reg_imm32(b,op);
1015                break;
1016          }
1017       }
1018    }
1019    
1020    /* Opcode emit start */
1021    static inline void ppc32_op_emit_start(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
1022    {
1023       cpu_gen_t *c = cpu->gen;
1024       jit_op_t *op;
1025    
1026       if (c->jit_op_array[b->ppc_trans_pos] == NULL)
1027          c->jit_op_current = &c->jit_op_array[b->ppc_trans_pos];
1028       else {
1029          for(op=c->jit_op_array[b->ppc_trans_pos];op;op=op->next)
1030             c->jit_op_current = &op->next;
1031       }
1032    }
1033    
1034    /* Generate the JIT code for the current page, given an op list */
1035    static int ppc32_op_gen_page(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
1036    {  
1037       struct ppc32_insn_tag *tag;
1038       cpu_gen_t *gcpu = cpu->gen;
1039       jit_op_t *iop;
1040       m_uint32_t cur_ia;
1041       u_char *jit_ptr;
1042       int i;
1043    
1044       /* Generate JIT opcodes */
1045       for(b->ppc_trans_pos=0;
1046           b->ppc_trans_pos<PPC32_INSN_PER_PAGE;
1047           b->ppc_trans_pos++)
1048       {
1049          ppc32_op_emit_start(cpu,b);
1050    
1051          cur_ia = b->start_ia + (b->ppc_trans_pos << 2);
1052    
1053          if (ppc32_jit_tcb_get_target_bit(b,cur_ia))
1054             ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);
1055    
1056          if (unlikely(!(tag = ppc32_jit_fetch_and_emit(cpu,b)))) {
1057             fprintf(stderr,"ppc32_op_gen_page: unable to fetch instruction.\n");
1058             return(-1);
1059          }
1060       }
1061    
1062       /*
1063        * Mark the first instruction as a potential target, as well as the
1064        * current IA value.
1065        */
1066       ppc32_op_emit_branch_target(cpu,b,b->start_ia);
1067       ppc32_op_emit_branch_target(cpu,b,cpu->ia);
1068    
1069       /* Optimize condition register and general registers */
1070       ppc32_op_optimize(gcpu,b);
1071    
1072       /* Generate JIT code for each instruction in page */
1073       for(i=0;i<PPC32_INSN_PER_PAGE;i++)
1074       {
1075          jit_ptr = b->jit_ptr;
1076    
1077    #if DEBUG_INSN_PERF_CNT
1078          ppc32_inc_perf_counter(b);
1079    #endif
1080    #if BREAKPOINT_ENABLE
1081          if (cpu->breakpoints_enabled)
1082             insn_emit_breakpoint(cpu,b);
1083    #endif
1084    
1085          /* Generate output code */
1086          ppc32_op_gen_list(b,i,gcpu->jit_op_array[i],jit_ptr);
1087    
1088          /* Adjust the JIT buffer if its size is not sufficient */
1089          ppc32_jit_tcb_adjust_buffer(cpu,b);
1090       }
1091    
1092       /* Apply patches and free opcodes */
1093       for(i=0;i<PPC32_INSN_PER_PAGE;i++) {
1094          for(iop=gcpu->jit_op_array[i];iop;iop=iop->next)
1095             if (iop->opcode == JIT_OP_INSN_OUTPUT)
1096                ppc32_jit_tcb_apply_patches(cpu,b,iop);
1097    
1098          jit_op_free_list(gcpu,gcpu->jit_op_array[i]);
1099          gcpu->jit_op_array[i] = NULL;
1100       }
1101    
1102       /* Add end of page (returns to caller) */
1103       ppc32_set_page_jump(cpu,b);
1104    
1105       /* Free patch tables */
1106       ppc32_jit_tcb_free_patches(b);
1107       return(0);
1108    }
1109    
1110    /* ======================================================================== */
1111    
1112  /* Compile a PowerPC instruction page */  /* Compile a PowerPC instruction page */
1113  static inline  static inline
1114  ppc32_jit_tcb_t *ppc32_jit_tcb_compile(cpu_ppc_t *cpu,m_uint32_t vaddr)  ppc32_jit_tcb_t *ppc32_jit_tcb_compile(cpu_ppc_t *cpu,m_uint32_t vaddr)
1115  {    {  
1116     ppc32_jit_tcb_t *block;     ppc32_jit_tcb_t *block;
    struct ppc32_insn_tag *tag;  
1117     m_uint32_t page_addr;     m_uint32_t page_addr;
    size_t len;  
1118    
1119     page_addr = vaddr & ~PPC32_MIN_PAGE_IMASK;     page_addr = vaddr & ~PPC32_MIN_PAGE_IMASK;
1120    
# Line 529  ppc32_jit_tcb_t *ppc32_jit_tcb_compile(c Line 1124  ppc32_jit_tcb_t *ppc32_jit_tcb_compile(c
1124     }     }
1125    
1126     /* Allocate the array used to convert PPC code ptr to native code ptr */     /* Allocate the array used to convert PPC code ptr to native code ptr */
1127     len = PPC32_MIN_PAGE_SIZE / sizeof(ppc_insn_t);     if (!(block->jit_insn_ptr = calloc(PPC32_INSN_PER_PAGE,sizeof(u_char *)))) {
   
    if (!(block->jit_insn_ptr = calloc(len,sizeof(u_char *)))) {  
1128        fprintf(stderr,"insn_page_compile: unable to create JIT mappings.\n");        fprintf(stderr,"insn_page_compile: unable to create JIT mappings.\n");
1129        goto error;        goto error;
1130     }     }
1131    
1132     /* Emit native code for each instruction */     /* Compile the page */
1133     block->ppc_trans_pos = 0;     if (ppc32_op_gen_page(cpu,block) == -1) {
1134          fprintf(stderr,"insn_page_compile: unable to compile page.\n");
1135     while(block->ppc_trans_pos < (PPC32_MIN_PAGE_SIZE/sizeof(ppc_insn_t)))        goto error;
    {  
       if (unlikely(!(tag = ppc32_jit_fetch_and_emit(cpu,block)))) {  
          fprintf(stderr,"insn_page_compile: unable to fetch instruction.\n");  
          goto error;  
       }  
   
 #if DEBUG_BLOCK_COMPILE  
       printf("Page 0x%8.8x: emitted tag 0x%8.8x/0x%8.8x\n",  
              block->start_ia,tag->mask,tag->value);  
 #endif  
   
       ppc32_jit_tcb_adjust_buffer(cpu,block);  
1136     }     }
1137      
    ppc32_jit_tcb_add_end(block);  
    ppc32_jit_tcb_apply_patches(cpu,block);  
    ppc32_jit_tcb_free_patches(block);  
   
1138     /* Add the block to the linked list */     /* Add the block to the linked list */
1139     block->next = cpu->tcb_list;     block->next = cpu->tcb_list;
1140     block->prev = NULL;     block->prev = NULL;
# Line 586  ppc32_jit_tcb_t *ppc32_jit_tcb_compile(c Line 1163  ppc32_jit_tcb_t *ppc32_jit_tcb_compile(c
1163     return NULL;     return NULL;
1164  }  }
1165    
1166    /* Recompile a page */
1167    int ppc32_jit_tcb_recompile(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
1168    {
1169    #if 0
1170       printf("PPC32-JIT: recompiling page 0x%8.8x\n",block->start_ia);
1171    #endif
1172    
1173       /* Free old code chunks */
1174       ppc32_jit_tcb_free_code_chunks(cpu,block);
1175    
1176       /* Reset code ptr array */
1177       memset(block->jit_insn_ptr,0,PPC32_INSN_PER_PAGE * sizeof(u_char *));
1178    
1179       /* Allocate the first JIT buffer */
1180       if (!(block->jit_buffer = exec_page_alloc(cpu)))
1181          return(-1);
1182    
1183       /* Recompile the page */
1184       if (ppc32_op_gen_page(cpu,block) == -1) {
1185          fprintf(stderr,"insn_page_compile: unable to recompile page.\n");
1186          return(-1);
1187       }
1188    
1189       block->target_undef_cnt = 0;
1190       return(0);
1191    }
1192    
1193  /* Run a compiled PowerPC instruction block */  /* Run a compiled PowerPC instruction block */
1194  static forced_inline  static forced_inline
1195  void ppc32_jit_tcb_run(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)  void ppc32_jit_tcb_run(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
# Line 611  void *ppc32_jit_run_cpu(cpu_gen_t *gen) Line 1215  void *ppc32_jit_run_cpu(cpu_gen_t *gen)
1215     m_uint32_t ia_hash;     m_uint32_t ia_hash;
1216     int timer_irq_check = 0;     int timer_irq_check = 0;
1217    
1218       ppc32_jit_init_hreg_mapping(cpu);
1219    
1220     if (pthread_create(&timer_irq_thread,NULL,(void *)ppc32_timer_irq_run,cpu))     if (pthread_create(&timer_irq_thread,NULL,(void *)ppc32_timer_irq_run,cpu))
1221     {     {
1222        fprintf(stderr,        fprintf(stderr,
# Line 661  void *ppc32_jit_run_cpu(cpu_gen_t *gen) Line 1267  void *ppc32_jit_run_cpu(cpu_gen_t *gen)
1267        /* Get the JIT block corresponding to IA register */        /* Get the JIT block corresponding to IA register */
1268        ia_hash = ppc32_jit_get_ia_hash(cpu->ia);        ia_hash = ppc32_jit_get_ia_hash(cpu->ia);
1269        block = cpu->exec_blk_map[ia_hash];        block = cpu->exec_blk_map[ia_hash];
1270          
1271        /* No block found, compile the page */        /* No block found, compile the page */
1272        if (unlikely(!block) || unlikely(!ppc32_jit_tcb_match(cpu,block)))        if (unlikely(!block) || unlikely(!ppc32_jit_tcb_match(cpu,block)))
1273        {        {

Legend:
Removed from v.8  
changed lines
  Added in v.9

  ViewVC Help
Powered by ViewVC 1.1.26