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

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

revision 31 by dpavlin, Mon Oct 8 16:20:40 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_sparc_instr.c,v 1.23 2006/07/24 22:32:44 debug Exp $   *  $Id: cpu_sparc_instr.c,v 1.25 2006/09/04 15:35:55 debug Exp $
29   *   *
30   *  SPARC instructions.   *  SPARC instructions.
31   *   *
# Line 155  X(bl_xcc) Line 155  X(bl_xcc)
155    
156    
157  /*  /*
158     *  ble
159     *
160     *  arg[0] = int32_t displacement compared to the start of the current page
161     */
162    X(ble)
163    {
164            MODE_uint_t old_pc = cpu->pc;
165            int n = (cpu->cd.sparc.ccr & SPARC_CCR_N) ? 1 : 0;
166            int v = (cpu->cd.sparc.ccr & SPARC_CCR_V) ? 1 : 0;
167            int z = (cpu->cd.sparc.ccr & SPARC_CCR_Z) ? 1 : 0;
168            int cond = (n ^ v) || z;
169            cpu->delay_slot = TO_BE_DELAYED;
170            ic[1].f(cpu, ic+1);
171            cpu->n_translated_instrs ++;
172            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
173                    /*  Note: Must be non-delayed when jumping to the new pc:  */
174                    cpu->delay_slot = NOT_DELAYED;
175                    if (cond) {
176                            old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
177                                << SPARC_INSTR_ALIGNMENT_SHIFT);
178                            cpu->pc = old_pc + (int32_t)ic->arg[0];
179                            quick_pc_to_pointers(cpu);
180                    }
181            } else
182                    cpu->delay_slot = NOT_DELAYED;
183    }
184    X(ble_xcc)
185    {
186            MODE_uint_t old_pc = cpu->pc;
187            int n = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_N)? 1:0;
188            int v = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_V)? 1:0;
189            int z = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_Z)? 1:0;
190            int cond = (n ^ v) || z;
191            cpu->delay_slot = TO_BE_DELAYED;
192            ic[1].f(cpu, ic+1);
193            cpu->n_translated_instrs ++;
194            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
195                    /*  Note: Must be non-delayed when jumping to the new pc:  */
196                    cpu->delay_slot = NOT_DELAYED;
197                    if (cond) {
198                            old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
199                                << SPARC_INSTR_ALIGNMENT_SHIFT);
200                            cpu->pc = old_pc + (int32_t)ic->arg[0];
201                            quick_pc_to_pointers(cpu);
202                    }
203            } else
204                    cpu->delay_slot = NOT_DELAYED;
205    }
206    
207    
208    /*
209   *  bne   *  bne
210   *   *
211   *  arg[0] = int32_t displacement compared to the start of the current page   *  arg[0] = int32_t displacement compared to the start of the current page
# Line 398  X(brnz) Line 449  X(brnz)
449    
450    
451  /*  /*
452     *  Save:
453     *
454     *  arg[0] = ptr to rs1
455     *  arg[1] = ptr to rs2 or an immediate value (int32_t)
456     *  arg[2] = ptr to rd (_after_ the register window change)
457     */
458    X(save_v9_imm)
459    {
460            MODE_uint_t rs = reg(ic->arg[0]) + (int32_t)ic->arg[1];
461            int cwp = cpu->cd.sparc.cwp;
462    
463            if (cpu->cd.sparc.cansave == 0) {
464                    fatal("save_v9_imm: spill trap. TODO\n");
465                    exit(1);
466            }
467    
468            if (cpu->cd.sparc.cleanwin - cpu->cd.sparc.canrestore == 0) {
469                    fatal("save_v9_imm: clean_window trap. TODO\n");
470                    exit(1);
471            }
472    
473            /*  Save away old in registers:  */
474            memcpy(&cpu->cd.sparc.r_inout[cwp][0], &cpu->cd.sparc.r[SPARC_REG_I0],
475                sizeof(cpu->cd.sparc.r[SPARC_REG_I0]) * N_SPARC_INOUT_REG);
476    
477            /*  Save away old local registers:  */
478            memcpy(&cpu->cd.sparc.r_local[cwp][0], &cpu->cd.sparc.r[SPARC_REG_L0],
479                sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);
480    
481            cpu->cd.sparc.cwp = (cwp + 1) % cpu->cd.sparc.cpu_type.nwindows;
482            cpu->cd.sparc.cansave --;
483            cpu->cd.sparc.canrestore ++;    /*  TODO: modulo here too?  */
484            cwp = cpu->cd.sparc.cwp;
485    
486            /*  The out registers become the new in registers:  */
487            memcpy(&cpu->cd.sparc.r[SPARC_REG_I0], &cpu->cd.sparc.r[SPARC_REG_O0],
488                sizeof(cpu->cd.sparc.r[SPARC_REG_O0]) * N_SPARC_INOUT_REG);
489    
490            /*  Read new local registers:  */
491            memcpy(&cpu->cd.sparc.r[SPARC_REG_L0], &cpu->cd.sparc.r_local[cwp][0],
492                sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);
493    
494            reg(ic->arg[2]) = rs;
495    }
496    
497    
498    /*
499     *  Restore:
500     */
501    X(restore)
502    {
503            int cwp = cpu->cd.sparc.cwp;
504    
505            if (cpu->cd.sparc.canrestore == 0) {
506                    fatal("restore: spill trap. TODO\n");
507                    exit(1);
508            }
509    
510            cpu->cd.sparc.cwp = cwp - 1;
511            if (cwp == 0)
512                    cpu->cd.sparc.cwp = cpu->cd.sparc.cpu_type.nwindows - 1;
513            cpu->cd.sparc.cansave ++;
514            cpu->cd.sparc.canrestore --;
515            cwp = cpu->cd.sparc.cwp;
516    
517            /*  The in registers become the new out registers:  */
518            memcpy(&cpu->cd.sparc.r[SPARC_REG_O0], &cpu->cd.sparc.r[SPARC_REG_I0],
519                sizeof(cpu->cd.sparc.r[SPARC_REG_O0]) * N_SPARC_INOUT_REG);
520    
521            /*  Read back the local registers:  */
522            memcpy(&cpu->cd.sparc.r[SPARC_REG_L0], &cpu->cd.sparc.r_local[cwp][0],
523                sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);
524    
525            /*  Read back the in registers:  */
526            memcpy(&cpu->cd.sparc.r[SPARC_REG_I0], &cpu->cd.sparc.r_inout[cwp][0],
527                sizeof(cpu->cd.sparc.r[SPARC_REG_I0]) * N_SPARC_INOUT_REG);
528    }
529    
530    
531    /*
532   *  Jump and link   *  Jump and link
533   *   *
534   *  arg[0] = ptr to rs1   *  arg[0] = ptr to rs1
# Line 556  X(retl_trace) Line 687  X(retl_trace)
687    
688    
689  /*  /*
690     *  Return
691     *
692     *  arg[0] = ptr to rs1
693     *  arg[1] = ptr to rs2 or an immediate value (int32_t)
694     */
695    X(return_imm)
696    {
697            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
698                / sizeof(struct sparc_instr_call);
699            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
700                << SPARC_INSTR_ALIGNMENT_SHIFT);
701            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
702    
703            cpu->delay_slot = TO_BE_DELAYED;
704            ic[1].f(cpu, ic+1);
705            cpu->n_translated_instrs ++;
706    
707            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
708                    /*  Note: Must be non-delayed when jumping to the new pc:  */
709                    cpu->delay_slot = NOT_DELAYED;
710                    cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
711                    quick_pc_to_pointers(cpu);
712                    instr(restore)(cpu, ic);
713            } else
714                    cpu->delay_slot = NOT_DELAYED;
715    }
716    X(return_reg)
717    {
718            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
719                / sizeof(struct sparc_instr_call);
720            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
721                << SPARC_INSTR_ALIGNMENT_SHIFT);
722            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
723    
724            cpu->delay_slot = TO_BE_DELAYED;
725            ic[1].f(cpu, ic+1);
726            cpu->n_translated_instrs ++;
727    
728            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
729                    /*  Note: Must be non-delayed when jumping to the new pc:  */
730                    cpu->delay_slot = NOT_DELAYED;
731                    cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
732                    quick_pc_to_pointers(cpu);
733                    instr(restore)(cpu, ic);
734            } else
735                    cpu->delay_slot = NOT_DELAYED;
736    }
737    X(return_imm_trace)
738    {
739            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
740                / sizeof(struct sparc_instr_call);
741            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
742                << SPARC_INSTR_ALIGNMENT_SHIFT);
743            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
744    
745            cpu->delay_slot = TO_BE_DELAYED;
746            ic[1].f(cpu, ic+1);
747            cpu->n_translated_instrs ++;
748    
749            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
750                    /*  Note: Must be non-delayed when jumping to the new pc:  */
751                    cpu->delay_slot = NOT_DELAYED;
752                    cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
753                    cpu_functioncall_trace(cpu, cpu->pc);
754                    quick_pc_to_pointers(cpu);
755                    instr(restore)(cpu, ic);
756            } else
757                    cpu->delay_slot = NOT_DELAYED;
758    }
759    X(return_reg_trace)
760    {
761            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
762                / sizeof(struct sparc_instr_call);
763            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
764                << SPARC_INSTR_ALIGNMENT_SHIFT);
765            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
766    
767            cpu->delay_slot = TO_BE_DELAYED;
768            ic[1].f(cpu, ic+1);
769            cpu->n_translated_instrs ++;
770    
771            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
772                    /*  Note: Must be non-delayed when jumping to the new pc:  */
773                    cpu->delay_slot = NOT_DELAYED;
774                    cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
775                    cpu_functioncall_trace(cpu, cpu->pc);
776                    quick_pc_to_pointers(cpu);
777                    instr(restore)(cpu, ic);
778            } else
779                    cpu->delay_slot = NOT_DELAYED;
780    }
781    
782    
783    /*
784   *  set:  Set a register to a value (e.g. sethi).   *  set:  Set a register to a value (e.g. sethi).
785   *   *
786   *  arg[0] = ptr to rd   *  arg[0] = ptr to rd
# Line 578  X(add)      { reg(ic->arg[2]) = reg(ic-> Line 803  X(add)      { reg(ic->arg[2]) = reg(ic->
803  X(add_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1]; }  X(add_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1]; }
804  X(and)      { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }  X(and)      { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
805  X(and_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) & (int32_t)ic->arg[1]; }  X(and_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) & (int32_t)ic->arg[1]; }
806    X(andn)     { reg(ic->arg[2]) = reg(ic->arg[0]) & ~reg(ic->arg[1]); }
807    X(andn_imm) { reg(ic->arg[2]) = reg(ic->arg[0]) & ~(int32_t)ic->arg[1]; }
808  X(or)       { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }  X(or)       { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
809  X(or_imm)   { reg(ic->arg[2]) = reg(ic->arg[0]) | (int32_t)ic->arg[1]; }  X(or_imm)   { reg(ic->arg[2]) = reg(ic->arg[0]) | (int32_t)ic->arg[1]; }
810  X(xor)      { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }  X(xor)      { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
# Line 625  X(udiv_imm) Line 852  X(udiv_imm)
852    
853    
854  /*  /*
  *  Save:  
  *  
  *  arg[0] = ptr to rs1  
  *  arg[1] = ptr to rs2 or an immediate value (int32_t)  
  *  arg[2] = ptr to rd (_after_ the register window change)  
  */  
 X(save_v9_imm)  
 {  
         MODE_uint_t rs = reg(ic->arg[0]) + (int32_t)ic->arg[1];  
         int cwp = cpu->cd.sparc.cwp;  
   
         if (cpu->cd.sparc.cansave == 0) {  
                 fatal("save_v9_imm: spill trap. TODO\n");  
                 exit(1);  
         }  
   
         if (cpu->cd.sparc.cleanwin - cpu->cd.sparc.canrestore == 0) {  
                 fatal("save_v9_imm: clean_window trap. TODO\n");  
                 exit(1);  
         }  
   
         /*  Save away old in registers:  */  
         memcpy(&cpu->cd.sparc.r_inout[cwp][0], &cpu->cd.sparc.r[SPARC_REG_I0],  
             sizeof(cpu->cd.sparc.r[SPARC_REG_I0]) * N_SPARC_INOUT_REG);  
   
         /*  Save away old local registers:  */  
         memcpy(&cpu->cd.sparc.r_local[cwp][0], &cpu->cd.sparc.r[SPARC_REG_L0],  
             sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);  
   
         cwp = cpu->cd.sparc.cwp = (cwp + 1) % cpu->cd.sparc.cpu_type.nwindows;  
         cpu->cd.sparc.cansave --;  
         cpu->cd.sparc.canrestore ++;    /*  TODO: modulo here too?  */  
   
         /*  The out registers become the new in registers:  */  
         memcpy(&cpu->cd.sparc.r[SPARC_REG_I0], &cpu->cd.sparc.r[SPARC_REG_O0],  
             sizeof(cpu->cd.sparc.r[SPARC_REG_O0]) * N_SPARC_INOUT_REG);  
   
         /*  Read new local registers:  */  
         memcpy(&cpu->cd.sparc.r[SPARC_REG_L0], &cpu->cd.sparc.r_local[cwp][0],  
             sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);  
   
         reg(ic->arg[2]) = rs;  
 }  
   
   
 /*  
855   *  Add with ccr update:   *  Add with ccr update:
856   *   *
857   *  arg[0] = ptr to rs1   *  arg[0] = ptr to rs1
# Line 1049  X(to_be_translated) Line 1230  X(to_be_translated)
1230                          /*  TODO: samepage  */                          /*  TODO: samepage  */
1231                          switch (rd + (cc << 5)) {                          switch (rd + (cc << 5)) {
1232                          case 0x01:      ic->f = instr(be);  break;                          case 0x01:      ic->f = instr(be);  break;
1233                            case 0x02:      ic->f = instr(ble); break;
1234                          case 0x03:      ic->f = instr(bl);  break;                          case 0x03:      ic->f = instr(bl);  break;
1235                            case 0x08:      ic->f = instr(ba);  break;
1236                          case 0x09:      ic->f = instr(bne); break;                          case 0x09:      ic->f = instr(bne); break;
1237                          case 0x0a:      ic->f = instr(bg); break;                          case 0x0a:      ic->f = instr(bg);  break;
1238                          case 0x0b:      ic->f = instr(bge); break;                          case 0x0b:      ic->f = instr(bge); break;
1239                          case 0x19:      ic->f = instr(bne_a); break;                          case 0x19:      ic->f = instr(bne_a);  break;
1240                          case 0x41:      ic->f = instr(be_xcc); break;                          case 0x41:      ic->f = instr(be_xcc); break;
1241                            case 0x42:      ic->f = instr(ble_xcc);break;
1242                          case 0x43:      ic->f = instr(bl_xcc); break;                          case 0x43:      ic->f = instr(bl_xcc); break;
1243                            case 0x48:      ic->f = instr(ba);     break;
1244                          case 0x4a:      ic->f = instr(bg_xcc); break;                          case 0x4a:      ic->f = instr(bg_xcc); break;
1245                          case 0x4b:      ic->f = instr(bge_xcc); break;                          case 0x4b:      ic->f = instr(bge_xcc);break;
1246                          default:fatal("Unimplemented branch, 0x%x\n",                          default:fatal("Unimplemented branch, 0x%x\n",
1247                                      rd + (cc<<5));                                      rd + (cc<<5));
1248                                  goto bad;                                  goto bad;
# Line 1075  X(to_be_translated) Line 1260  X(to_be_translated)
1260                          case 0x01:      ic->f = instr(be);  break;                          case 0x01:      ic->f = instr(be);  break;
1261                          case 0x03:      ic->f = instr(bl);  break;                          case 0x03:      ic->f = instr(bl);  break;
1262                          case 0x08:      ic->f = instr(ba);  break;                          case 0x08:      ic->f = instr(ba);  break;
1263                            case 0x09:      ic->f = instr(bne); break;
1264                          case 0x0b:      ic->f = instr(bge); break;                          case 0x0b:      ic->f = instr(bge); break;
1265                          default:fatal("Unimplemented branch rd=%i\n", rd);                          default:fatal("Unimplemented branch rd=%i\n", rd);
1266                                  goto bad;                                  goto bad;
# Line 1127  X(to_be_translated) Line 1313  X(to_be_translated)
1313                  case 2: /*  or  */                  case 2: /*  or  */
1314                  case 3: /*  xor  */                  case 3: /*  xor  */
1315                  case 4: /*  sub  */                  case 4: /*  sub  */
1316                    case 5: /*  andn  */
1317                  case 14:/*  udiv  */                  case 14:/*  udiv  */
1318                  case 16:/*  addcc  */                  case 16:/*  addcc  */
1319                  case 17:/*  andcc  */                  case 17:/*  andcc  */
# Line 1145  X(to_be_translated) Line 1332  X(to_be_translated)
1332                                  case 2: ic->f = instr(or_imm); break;                                  case 2: ic->f = instr(or_imm); break;
1333                                  case 3: ic->f = instr(xor_imm); break;                                  case 3: ic->f = instr(xor_imm); break;
1334                                  case 4: ic->f = instr(sub_imm); break;                                  case 4: ic->f = instr(sub_imm); break;
1335                                    case 5: ic->f = instr(andn_imm); break;
1336                                  case 14:ic->f = instr(udiv_imm); break;                                  case 14:ic->f = instr(udiv_imm); break;
1337                                  case 16:ic->f = instr(addcc_imm); break;                                  case 16:ic->f = instr(addcc_imm); break;
1338                                  case 17:ic->f = instr(andcc_imm); break;                                  case 17:ic->f = instr(andcc_imm); break;
# Line 1191  X(to_be_translated) Line 1379  X(to_be_translated)
1379                                  case 2: ic->f = instr(or); break;                                  case 2: ic->f = instr(or); break;
1380                                  case 3: ic->f = instr(xor); break;                                  case 3: ic->f = instr(xor); break;
1381                                  case 4: ic->f = instr(sub); break;                                  case 4: ic->f = instr(sub); break;
1382                                    case 5: ic->f = instr(andn); break;
1383                                  case 14:ic->f = instr(udiv); break;                                  case 14:ic->f = instr(udiv); break;
1384                                  case 16:ic->f = instr(addcc); break;                                  case 16:ic->f = instr(addcc); break;
1385                                  case 17:ic->f = instr(andcc); break;                                  case 17:ic->f = instr(andcc); break;
# Line 1358  X(to_be_translated) Line 1547  X(to_be_translated)
1547                          }                          }
1548                          break;                          break;
1549    
1550                    case 57:/*  return  */
1551                            ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1552    
1553                            if (use_imm) {
1554                                    ic->arg[1] = siconst;
1555                                    ic->f = instr(return_imm);
1556                            } else {
1557                                    ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1558                                    ic->f = instr(return_reg);
1559                            }
1560    
1561                            /*  special trace case:  */
1562                            if (cpu->machine->show_trace_tree) {
1563                                    if (use_imm)
1564                                            ic->f = instr(return_imm_trace);
1565                                    else
1566                                            ic->f = instr(return_reg_trace);
1567                            }
1568                            break;
1569    
1570                  default:fatal("TODO: unimplemented op2=%i for main "                  default:fatal("TODO: unimplemented op2=%i for main "
1571                              "opcode %i\n", op2, main_opcode);                              "opcode %i\n", op2, main_opcode);
1572                          goto bad;                          goto bad;

Legend:
Removed from v.31  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26