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

Legend:
Removed from v.20  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26