/[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 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_sparc_instr.c,v 1.5 2006/02/09 22:40:27 debug Exp $   *  $Id: cpu_sparc_instr.c,v 1.18 2006/05/17 20:27:31 debug Exp $
29   *   *
30   *  SPARC instructions.   *  SPARC instructions.
31   *   *
# Line 47  X(nop) Line 47  X(nop)
47  /*****************************************************************************/  /*****************************************************************************/
48    
49    
50    /*
51     *  call
52     *
53     *  arg[0] = int32_t displacement compared to the current instruction
54     *  arg[1] = int32_t displacement of current instruction compared to
55     *           start of the page
56     */
57    X(call)
58    {
59            MODE_uint_t old_pc = cpu->pc;
60            old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
61                << SPARC_INSTR_ALIGNMENT_SHIFT);
62            old_pc += (int32_t)ic->arg[1];
63            cpu->cd.sparc.r[SPARC_REG_O7] = old_pc;
64            cpu->delay_slot = TO_BE_DELAYED;
65            ic[1].f(cpu, ic+1);
66            cpu->n_translated_instrs ++;
67            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
68                    /*  Note: Must be non-delayed when jumping to the new pc:  */
69                    cpu->delay_slot = NOT_DELAYED;
70                    cpu->pc = old_pc + (int32_t)ic->arg[0];
71                    quick_pc_to_pointers(cpu);
72            } else
73                    cpu->delay_slot = NOT_DELAYED;
74    }
75    X(call_trace)
76    {
77            MODE_uint_t old_pc = cpu->pc;
78            old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
79                << SPARC_INSTR_ALIGNMENT_SHIFT);
80            old_pc += (int32_t)ic->arg[1];
81            cpu->cd.sparc.r[SPARC_REG_O7] = old_pc;
82            cpu->delay_slot = TO_BE_DELAYED;
83            ic[1].f(cpu, ic+1);
84            cpu->n_translated_instrs ++;
85            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
86                    /*  Note: Must be non-delayed when jumping to the new pc:  */
87                    cpu->delay_slot = NOT_DELAYED;
88                    cpu->pc = old_pc + (int32_t)ic->arg[0];
89                    cpu_functioncall_trace(cpu, cpu->pc);
90                    quick_pc_to_pointers(cpu);
91            } else
92                    cpu->delay_slot = NOT_DELAYED;
93    }
94    
95    
96    /*
97     *  ba
98     *
99     *  arg[0] = int32_t displacement compared to the start of the current page
100     */
101    X(ba)
102    {
103            MODE_uint_t old_pc = cpu->pc;
104            cpu->delay_slot = TO_BE_DELAYED;
105            ic[1].f(cpu, ic+1);
106            cpu->n_translated_instrs ++;
107            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
108                    /*  Note: Must be non-delayed when jumping to the new pc:  */
109                    cpu->delay_slot = NOT_DELAYED;
110                    old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
111                        << SPARC_INSTR_ALIGNMENT_SHIFT);
112                    cpu->pc = old_pc + (int32_t)ic->arg[0];
113                    quick_pc_to_pointers(cpu);
114            } else
115                    cpu->delay_slot = NOT_DELAYED;
116    }
117    
118    
119    /*
120     *  Jump and link
121     *
122     *  arg[0] = ptr to rs1
123     *  arg[1] = ptr to rs2 or an immediate value (int32_t)
124     *  arg[2] = ptr to rd
125     */
126    X(jmpl_imm)
127    {
128            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
129                / sizeof(struct sparc_instr_call);
130            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
131                << SPARC_INSTR_ALIGNMENT_SHIFT);
132            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
133            reg(ic->arg[2]) = cpu->pc;
134    
135            cpu->delay_slot = TO_BE_DELAYED;
136            ic[1].f(cpu, ic+1);
137            cpu->n_translated_instrs ++;
138    
139            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
140                    /*  Note: Must be non-delayed when jumping to the new pc:  */
141                    cpu->delay_slot = NOT_DELAYED;
142                    cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
143                    quick_pc_to_pointers(cpu);
144            } else
145                    cpu->delay_slot = NOT_DELAYED;
146    }
147    X(jmpl_imm_no_rd)
148    {
149            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
150                / sizeof(struct sparc_instr_call);
151            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
152                << SPARC_INSTR_ALIGNMENT_SHIFT);
153            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
154    
155            cpu->delay_slot = TO_BE_DELAYED;
156            ic[1].f(cpu, ic+1);
157            cpu->n_translated_instrs ++;
158    
159            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
160                    /*  Note: Must be non-delayed when jumping to the new pc:  */
161                    cpu->delay_slot = NOT_DELAYED;
162                    cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
163                    quick_pc_to_pointers(cpu);
164            } else
165                    cpu->delay_slot = NOT_DELAYED;
166    }
167    X(jmpl_reg)
168    {
169            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
170                / sizeof(struct sparc_instr_call);
171            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
172                << SPARC_INSTR_ALIGNMENT_SHIFT);
173            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
174            reg(ic->arg[2]) = cpu->pc;
175    
176            cpu->delay_slot = TO_BE_DELAYED;
177            ic[1].f(cpu, ic+1);
178            cpu->n_translated_instrs ++;
179    
180            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
181                    /*  Note: Must be non-delayed when jumping to the new pc:  */
182                    cpu->delay_slot = NOT_DELAYED;
183                    cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
184                    quick_pc_to_pointers(cpu);
185            } else
186                    cpu->delay_slot = NOT_DELAYED;
187    }
188    X(jmpl_reg_no_rd)
189    {
190            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
191                / sizeof(struct sparc_instr_call);
192            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
193                << SPARC_INSTR_ALIGNMENT_SHIFT);
194            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
195    
196            cpu->delay_slot = TO_BE_DELAYED;
197            ic[1].f(cpu, ic+1);
198            cpu->n_translated_instrs ++;
199    
200            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
201                    /*  Note: Must be non-delayed when jumping to the new pc:  */
202                    cpu->delay_slot = NOT_DELAYED;
203                    cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
204                    quick_pc_to_pointers(cpu);
205            } else
206                    cpu->delay_slot = NOT_DELAYED;
207    }
208    
209    
210    X(jmpl_imm_trace)
211    {
212            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
213                / sizeof(struct sparc_instr_call);
214            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
215                << SPARC_INSTR_ALIGNMENT_SHIFT);
216            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
217            reg(ic->arg[2]) = cpu->pc;
218    
219            cpu->delay_slot = TO_BE_DELAYED;
220            ic[1].f(cpu, ic+1);
221            cpu->n_translated_instrs ++;
222    
223            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
224                    /*  Note: Must be non-delayed when jumping to the new pc:  */
225                    cpu->delay_slot = NOT_DELAYED;
226                    cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
227                    cpu_functioncall_trace(cpu, cpu->pc);
228                    quick_pc_to_pointers(cpu);
229            } else
230                    cpu->delay_slot = NOT_DELAYED;
231    }
232    X(jmpl_reg_trace)
233    {
234            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
235                / sizeof(struct sparc_instr_call);
236            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
237                << SPARC_INSTR_ALIGNMENT_SHIFT);
238            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
239            reg(ic->arg[2]) = cpu->pc;
240    
241            cpu->delay_slot = TO_BE_DELAYED;
242            ic[1].f(cpu, ic+1);
243            cpu->n_translated_instrs ++;
244    
245            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
246                    /*  Note: Must be non-delayed when jumping to the new pc:  */
247                    cpu->delay_slot = NOT_DELAYED;
248                    cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
249                    cpu_functioncall_trace(cpu, cpu->pc);
250                    quick_pc_to_pointers(cpu);
251            } else
252                    cpu->delay_slot = NOT_DELAYED;
253    }
254    X(retl_trace)
255    {
256            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
257                / sizeof(struct sparc_instr_call);
258            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
259                << SPARC_INSTR_ALIGNMENT_SHIFT);
260            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
261    
262            cpu->delay_slot = TO_BE_DELAYED;
263            ic[1].f(cpu, ic+1);
264            cpu->n_translated_instrs ++;
265    
266            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
267                    /*  Note: Must be non-delayed when jumping to the new pc:  */
268                    cpu->delay_slot = NOT_DELAYED;
269                    cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
270                    quick_pc_to_pointers(cpu);
271                    cpu_functioncall_trace_return(cpu);
272            } else
273                    cpu->delay_slot = NOT_DELAYED;
274    }
275    
276    
277    /*
278     *  set:  Set a register to a value (e.g. sethi).
279     *
280     *  arg[0] = ptr to rd
281     *  arg[1] = value (uint32_t)
282     */
283    X(set)
284    {
285            reg(ic->arg[0]) = (uint32_t)ic->arg[1];
286    }
287    
288    
289    /*
290     *  Computational/arithmetic instructions:
291     *
292     *  arg[0] = ptr to rs1
293     *  arg[1] = ptr to rs2 or an immediate value (int32_t)
294     *  arg[2] = ptr to rd
295     */
296    X(add)      { reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
297    X(add_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1]; }
298    X(and)      { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
299    X(and_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) & (int32_t)ic->arg[1]; }
300    X(or)       { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
301    X(or_imm)   { reg(ic->arg[2]) = reg(ic->arg[0]) | (int32_t)ic->arg[1]; }
302    X(xor)      { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
303    X(xor_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) ^ (int32_t)ic->arg[1]; }
304    X(sub)      { reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
305    X(sub_imm)  { reg(ic->arg[2]) = reg(ic->arg[0]) - (int32_t)ic->arg[1]; }
306    
307    X(sll)      { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) <<
308                    (reg(ic->arg[1]) & 31); }
309    X(sllx)     { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) <<
310                    (reg(ic->arg[1]) & 63); }
311    X(sll_imm)  { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) << ic->arg[1]; }
312    X(sllx_imm) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << ic->arg[1]; }
313    
314    X(srl)      { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) >>
315                    (reg(ic->arg[1]) & 31); }
316    X(srlx)     { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >>
317                    (reg(ic->arg[1]) & 63); }
318    X(srl_imm)  { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) >> ic->arg[1]; }
319    X(srlx_imm) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> ic->arg[1]; }
320    
321    X(sra)      { reg(ic->arg[2]) = (int32_t)reg(ic->arg[0]) >>
322                    (reg(ic->arg[1]) & 31); }
323    X(srax)     { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >>
324                    (reg(ic->arg[1]) & 63); }
325    X(sra_imm)  { reg(ic->arg[2]) = (int32_t)reg(ic->arg[0]) >> ic->arg[1]; }
326    X(srax_imm) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> ic->arg[1]; }
327    
328    
329    /*
330     *  Subtract with ccr update:
331     *
332     *  arg[0] = ptr to rs1
333     *  arg[1] = ptr to rs2 or an immediate value (int32_t)
334     *  arg[2] = ptr to rd
335     */
336    int32_t sparc_subcc32(struct cpu *cpu, int32_t rs1, int32_t rs2);
337    #ifdef MODE32
338    int32_t sparc_subcc32(struct cpu *cpu, int32_t rs1, int32_t rs2)
339    #else
340    int64_t sparc_subcc64(struct cpu *cpu, int64_t rs1, int64_t rs2)
341    #endif
342    {
343            int cc = 0, sign1 = 0, sign2 = 0, signd = 0, mask = SPARC_CCR_ICC_MASK;
344            MODE_int_t rd = rs1 - rs2;
345            if (rd == 0)
346                    cc = SPARC_CCR_Z;
347            else if (rd < 0)
348                    cc = SPARC_CCR_N, signd = 1;
349            if (rs1 < 0)
350                    sign1 = 1;
351            if (rs2 < 0)
352                    sign2 = 1;
353            if (sign1 != sign2 && sign1 != signd)
354                    cc |= SPARC_CCR_V;
355            /*  TODO: SPARC_CCR_C  */
356    #ifndef MODE32
357            mask <<= SPARC_CCR_XCC_SHIFT;
358            cc <<= SPARC_CCR_XCC_SHIFT;
359    #endif
360            cpu->cd.sparc.ccr &= ~mask;
361            cpu->cd.sparc.ccr |= cc;
362            return rd;
363    }
364    X(subcc)
365    {
366            /*  Like sub, but updates the ccr, and does both 32-bit and
367                64-bit comparison at the same time.  */
368            MODE_int_t rs1 = reg(ic->arg[0]), rs2 = reg(ic->arg[1]), rd;
369            rd = sparc_subcc32(cpu, rs1, rs2);
370    #ifndef MODE32
371            rd = sparc_subcc64(cpu, rs1, rs2);
372    #endif
373            reg(ic->arg[2]) = rd;
374    }
375    X(subcc_imm)
376    {
377            MODE_int_t rs1 = reg(ic->arg[0]), rs2 = (int32_t)ic->arg[1], rd;
378            rd = sparc_subcc32(cpu, rs1, rs2);
379    #ifndef MODE32
380            rd = sparc_subcc64(cpu, rs1, rs2);
381    #endif
382            reg(ic->arg[2]) = rd;
383    }
384    
385    
386    /*
387     *  rd:  Read special register:
388     *
389     *  arg[2] = ptr to rd
390     */
391    X(rd_psr)
392    {
393            reg(ic->arg[2]) = cpu->cd.sparc.psr;
394    }
395    
396    
397    /*
398     *  wrpr:  Write to privileged register
399     *
400     *  arg[0] = ptr to rs1
401     *  arg[1] = ptr to rs2 or an immediate value (int32_t)
402     */
403    X(wrpr_tick)
404    {
405            cpu->cd.sparc.tick = (uint32_t) (reg(ic->arg[0]) ^ reg(ic->arg[1]));
406    }
407    X(wrpr_tick_imm)
408    {
409            cpu->cd.sparc.tick = (uint32_t) (reg(ic->arg[0]) ^ (int32_t)ic->arg[1]);
410    }
411    X(wrpr_pil)
412    {
413            cpu->cd.sparc.pil = (reg(ic->arg[0]) ^ reg(ic->arg[1]))
414                & SPARC_PIL_MASK;
415    }
416    X(wrpr_pil_imm)
417    {
418            cpu->cd.sparc.pil = (reg(ic->arg[0]) ^ (int32_t)ic->arg[1])
419                & SPARC_PIL_MASK;
420    }
421    X(wrpr_pstate)
422    {
423            sparc_update_pstate(cpu, reg(ic->arg[0]) ^ reg(ic->arg[1]));
424    }
425    X(wrpr_pstate_imm)
426    {
427            sparc_update_pstate(cpu, reg(ic->arg[0]) ^ (int32_t)ic->arg[1]);
428    }
429    
430    
431    /*****************************************************************************/
432    
433    
434  X(end_of_page)  X(end_of_page)
435  {  {
436          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
# Line 56  X(end_of_page) Line 440  X(end_of_page)
440              SPARC_INSTR_ALIGNMENT_SHIFT);              SPARC_INSTR_ALIGNMENT_SHIFT);
441    
442          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
443          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
444    
445          /*  end_of_page doesn't count as an executed instruction:  */          /*  end_of_page doesn't count as an executed instruction:  */
446          cpu->n_translated_instrs --;          cpu->n_translated_instrs --;
447  }  }
448    
449    
450    X(end_of_page2)
451    {
452            /*  Synchronize PC on the _second_ instruction on the next page:  */
453            int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
454                / sizeof(struct sparc_instr_call);
455            cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
456                << SPARC_INSTR_ALIGNMENT_SHIFT);
457            cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
458    
459            /*  This doesn't count as an executed instruction.  */
460            cpu->n_translated_instrs --;
461    
462            quick_pc_to_pointers(cpu);
463    
464            if (cpu->delay_slot == NOT_DELAYED)
465                    return;
466    
467            fatal("end_of_page2: fatal error, we're in a delay slot\n");
468            exit(1);
469    }
470    
471    
472  /*****************************************************************************/  /*****************************************************************************/
473    
474    
475  /*  /*
476   *  sparc_instr_to_be_translated():   *  sparc_instr_to_be_translated():
477   *   *
478   *  Translate an instruction word into an sparc_instr_call. ic is filled in with   *  Translate an instruction word into a sparc_instr_call. ic is filled in with
479   *  valid data for the translated instruction, or a "nothing" instruction if   *  valid data for the translated instruction, or a "nothing" instruction if
480   *  there was a translation failure. The newly translated instruction is then   *  there was a translation failure. The newly translated instruction is then
481   *  executed.   *  executed.
482   */   */
483  X(to_be_translated)  X(to_be_translated)
484  {  {
485          uint64_t addr, low_pc;          MODE_uint_t addr;
486  #ifdef DYNTRANS_BACKEND          int low_pc;
487          int simple = 0;          int in_crosspage_delayslot = 0;
 #endif  
488          uint32_t iword;          uint32_t iword;
489          unsigned char *page;          unsigned char *page;
490          unsigned char ib[4];          unsigned char ib[4];
491          int main_opcode;          int main_opcode, op2, rd, rs1, rs2, btype, asi, cc, p, use_imm, x64 = 0;
492            int32_t tmpi32, siconst;
493          /* void (*samepage_function)(struct cpu *, struct sparc_instr_call *);*/          /* void (*samepage_function)(struct cpu *, struct sparc_instr_call *);*/
494    
495          /*  Figure out the (virtual) address of the instruction:  */          /*  Figure out the (virtual) address of the instruction:  */
496          low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)          low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
497              / sizeof(struct sparc_instr_call);              / sizeof(struct sparc_instr_call);
498    
499            /*  Special case for branch with delayslot on the next page:  */
500            if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
501                    /*  fatal("[ delay-slot translation across page "
502                        "boundary ]\n");  */
503                    in_crosspage_delayslot = 1;
504            }
505    
506          addr = cpu->pc & ~((SPARC_IC_ENTRIES_PER_PAGE-1)          addr = cpu->pc & ~((SPARC_IC_ENTRIES_PER_PAGE-1)
507              << SPARC_INSTR_ALIGNMENT_SHIFT);              << SPARC_INSTR_ALIGNMENT_SHIFT);
508          addr += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
# Line 96  X(to_be_translated) Line 510  X(to_be_translated)
510          addr &= ~((1 << SPARC_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << SPARC_INSTR_ALIGNMENT_SHIFT) - 1);
511    
512          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
513    #ifdef MODE32
514          page = cpu->cd.sparc.host_load[addr >> 12];          page = cpu->cd.sparc.host_load[addr >> 12];
515    #else
516            {
517                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
518                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
519                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
520                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
521                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
522                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
523                        DYNTRANS_L3N)) & mask3;
524                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.sparc.l1_64[x1];
525                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
526                    page = l3->host_load[x3];
527            }
528    #endif
529    
530          if (page != NULL) {          if (page != NULL) {
531                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT!\n");  */
532                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xffc), sizeof(ib));
533          } else {          } else {
534                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS!\n");  */
535                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
# Line 111  X(to_be_translated) Line 540  X(to_be_translated)
540                  }                  }
541          }          }
542    
543          iword = *((uint32_t *)&ib[0]);          /*  SPARC instruction words are always big-endian. Convert
544                to host order:  */
545  #ifdef HOST_LITTLE_ENDIAN          iword = BE32_TO_HOST( *((uint32_t *)&ib[0]) );
         iword = ((iword & 0xff) << 24) |  
                 ((iword & 0xff00) << 8) |  
                 ((iword & 0xff0000) >> 8) |  
                 ((iword & 0xff000000) >> 24);  
 #endif  
546    
547    
548  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
# Line 130  X(to_be_translated) Line 554  X(to_be_translated)
554           *  Translate the instruction:           *  Translate the instruction:
555           */           */
556    
557          main_opcode = iword >> 26;          main_opcode = iword >> 30;
558            rd = (iword >> 25) & 31;
559            btype = rd & (N_SPARC_BRANCH_TYPES - 1);
560            rs1 = (iword >> 14) & 31;
561            use_imm = (iword >> 13) & 1;
562            asi = (iword >> 5) & 0xff;
563            rs2 = iword & 31;
564            siconst = (int16_t)((iword & 0x1fff) << 3) >> 3;
565            op2 = (main_opcode == 0)? ((iword >> 22) & 7) : ((iword >> 19) & 0x3f);
566            cc = (iword >> 20) & 3;
567            p = (iword >> 19) & 1;
568    
569          switch (main_opcode) {          switch (main_opcode) {
570    
571          default:goto bad;          case 0: switch (op2) {
572    
573                    case 2: /*  branch (32-bit integer comparison)  */
574                            tmpi32 = (iword << 10);
575                            tmpi32 >>= 8;
576                            ic->arg[0] = (int32_t)tmpi32 + (addr & 0xffc);
577                            /*  rd contains the annul bit concatenated with 4 bits
578                                of condition code:  */
579                            /*  TODO: samepage  */
580                            switch (rd) {
581                            case 0x08:/*  ba  */
582                                    ic->f = instr(ba);
583                                    break;
584                            default:goto bad;
585                            }
586                            break;
587    
588                    case 4: /*  sethi  */
589                            ic->arg[0] = (size_t)&cpu->cd.sparc.r[rd];
590                            ic->arg[1] = (iword & 0x3fffff) << 10;
591                            ic->f = instr(set);
592                            if (rd == SPARC_ZEROREG)
593                                    ic->f = instr(nop);
594                            break;
595    
596                    default:fatal("TODO: unimplemented op2=%i for main "
597                                "opcode %i\n", op2, main_opcode);
598                            goto bad;
599                    }
600                    break;
601    
602            case 1: /*  call and link  */
603                    tmpi32 = (iword << 2);
604                    ic->arg[0] = (int32_t)tmpi32;
605                    ic->arg[1] = addr & 0xffc;
606                    if (cpu->machine->show_trace_tree)
607                            ic->f = instr(call_trace);
608                    else
609                            ic->f = instr(call);
610                    /*  TODO: samepage  */
611                    break;
612    
613            case 2: switch (op2) {
614    
615                    case 0: /*  add  */
616                    case 1: /*  and  */
617                    case 2: /*  or  */
618                    case 3: /*  xor  */
619                    case 4: /*  sub  */
620                    case 20:/*  subcc (cmp)  */
621                    case 37:/*  sll  */
622                    case 38:/*  srl  */
623                    case 39:/*  sra  */
624                            ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
625                            ic->f = NULL;
626                            if (use_imm) {
627                                    ic->arg[1] = siconst;
628                                    switch (op2) {
629                                    case 0: ic->f = instr(add_imm); break;
630                                    case 1: ic->f = instr(and_imm); break;
631                                    case 2: ic->f = instr(or_imm); break;
632                                    case 3: ic->f = instr(xor_imm); break;
633                                    case 4: ic->f = instr(sub_imm); break;
634                                    case 20:ic->f = instr(subcc_imm); break;
635                                    case 37:if (siconst & 0x1000) {
636                                                    ic->f = instr(sllx_imm);
637                                                    ic->arg[1] &= 63;
638                                                    x64 = 1;
639                                            } else {
640                                                    ic->f = instr(sll_imm);
641                                                    ic->arg[1] &= 31;
642                                            }
643                                            break;
644                                    case 38:if (siconst & 0x1000) {
645                                                    ic->f = instr(srlx_imm);
646                                                    ic->arg[1] &= 63;
647                                                    x64 = 1;
648                                            } else {
649                                                    ic->f = instr(srl_imm);
650                                                    ic->arg[1] &= 31;
651                                            }
652                                            break;
653                                    case 39:if (siconst & 0x1000) {
654                                                    ic->f = instr(srax_imm);
655                                                    ic->arg[1] &= 63;
656                                                    x64 = 1;
657                                            } else {
658                                                    ic->f = instr(sra_imm);
659                                                    ic->arg[1] &= 31;
660                                            }
661                                            break;
662                                    }
663                            } else {
664                                    ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
665                                    switch (op2) {
666                                    case 0: ic->f = instr(add); break;
667                                    case 1: ic->f = instr(and); break;
668                                    case 2: ic->f = instr(or); break;
669                                    case 3: ic->f = instr(xor); break;
670                                    case 4: ic->f = instr(sub); break;
671                                    case 20:ic->f = instr(subcc); break;
672                                    case 37:if (siconst & 0x1000) {
673                                                    ic->f = instr(sllx);
674                                                    x64 = 1;
675                                            } else
676                                                    ic->f = instr(sll);
677                                            break;
678                                    case 38:if (siconst & 0x1000) {
679                                                    ic->f = instr(srlx);
680                                                    x64 = 1;
681                                            } else
682                                                    ic->f = instr(srl);
683                                            break;
684                                    case 39:if (siconst & 0x1000) {
685                                                    ic->f = instr(srax);
686                                                    x64 = 1;
687                                            } else
688                                                    ic->f = instr(sra);
689                                            break;
690                                    }
691                            }
692                            if (ic->f == NULL) {
693                                    fatal("TODO: Unimplemented instruction "
694                                        "(possibly missed use_imm impl.)\n");
695                                    goto bad;
696                            }
697                            ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
698                            if (rd == SPARC_ZEROREG) {
699                                    /*  Opcodes which update the ccr should use
700                                        the scratch register instead of being
701                                        turned into a nop, when the zero register
702                                        is used as the destination:  */
703                                    switch (op2) {
704                                    case 20:/*  subcc  */
705                                            ic->arg[2] = (size_t)
706                                                &cpu->cd.sparc.scratch;
707                                            break;
708                                    default:ic->f = instr(nop);
709                                    }
710                            }
711                            break;
712    
713                    case 41:/*  rd %psr,%gpr on pre-sparcv9  */
714                            if (cpu->is_32bit) {
715                                    ic->f = instr(rd_psr);
716                                    ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
717                                    if (rd == SPARC_ZEROREG)
718                                            ic->f = instr(nop);
719                            } else {
720                                    fatal("opcode 2,41 not yet implemented"
721                                        " for 64-bit cpus\n");
722                                    goto bad;
723                            }
724                            break;
725    
726                    case 48:/*  wr  (Note: works as xor)  */
727                            ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
728                            if (use_imm) {
729                                    ic->arg[1] = siconst;
730                                    ic->f = instr(xor_imm);
731                            } else {
732                                    ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
733                                    ic->f = instr(xor);
734                            }
735                            ic->arg[2] = (size_t) NULL;
736                            switch (rd) {
737                            case 0: ic->arg[2] = (size_t)&cpu->cd.sparc.y;
738                                    break;
739                            case 6: ic->arg[2] = (size_t)&cpu->cd.sparc.fprs;
740                                    break;
741                            case 0x17:
742                                    ic->arg[2] = (size_t)&cpu->cd.sparc.tick_cmpr;
743                                    break;
744                            }
745                            if (ic->arg[2] == (size_t)NULL) {
746                                    fatal("TODO: Unimplemented wr instruction, "
747                                        "rd = 0x%02x\n", rd);
748                                    goto bad;
749                            }
750                            break;
751    
752                    case 50:/*  wrpr  (Note: works as xor)  */
753                            ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
754                            ic->f = NULL;
755                            if (use_imm) {
756                                    ic->arg[1] = siconst;
757                                    switch (rd) {
758                                    case 4: ic->f = instr(wrpr_tick_imm); break;
759                                    case 6: ic->f = instr(wrpr_pstate_imm); break;
760                                    case 8: ic->f = instr(wrpr_pil_imm); break;
761                                    }
762                            } else {
763                                    ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
764                                    switch (rd) {
765                                    case 4: ic->f = instr(wrpr_tick); break;
766                                    case 6: ic->f = instr(wrpr_pstate); break;
767                                    case 8: ic->f = instr(wrpr_pil); break;
768                                    }
769                            }
770                            if (ic->f == NULL) {
771                                    fatal("TODO: Unimplemented wrpr instruction,"
772                                        " rd = 0x%02x\n", rd);
773                                    goto bad;
774                            }
775                            break;
776    
777                    case 56:/*  jump and link  */
778                            ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
779                            ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
780                            if (rd == SPARC_ZEROREG)
781                                    ic->arg[2] = (size_t)&cpu->cd.sparc.scratch;
782    
783                            if (use_imm) {
784                                    ic->arg[1] = siconst;
785                                    if (rd == SPARC_ZEROREG)
786                                            ic->f = instr(jmpl_imm_no_rd);
787                                    else
788                                            ic->f = instr(jmpl_imm);
789                            } else {
790                                    ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
791                                    if (rd == SPARC_ZEROREG)
792                                            ic->f = instr(jmpl_reg_no_rd);
793                                    else
794                                            ic->f = instr(jmpl_reg);
795                            }
796    
797                            /*  special trace case:  */
798                            if (cpu->machine->show_trace_tree) {
799                                    if (iword == 0x81c3e008)
800                                            ic->f = instr(retl_trace);
801                                    else {
802                                            if (use_imm)
803                                                    ic->f = instr(jmpl_imm_trace);
804                                            else
805                                                    ic->f = instr(jmpl_reg_trace);
806                                    }
807                            }
808                            break;
809    
810                    default:fatal("TODO: unimplemented op2=%i for main "
811                                "opcode %i\n", op2, main_opcode);
812                            goto bad;
813                    }
814                    break;
815    
816            default:fatal("TODO: unimplemented main opcode %i\n", main_opcode);
817                    goto bad;
818            }
819    
820    
821            if (x64 && cpu->is_32bit) {
822                    fatal("TODO: 64-bit instr on 32-bit cpu\n");
823                    goto bad;
824          }          }
825    
826    

Legend:
Removed from v.22  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26