/[gxemul]/trunk/src/cpus/cpu_sh_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_sh_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 30 by dpavlin, Mon Oct 8 16:20:40 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_sh_instr.c,v 1.3 2005/11/06 22:41:12 debug Exp $   *  $Id: cpu_sh_instr.c,v 1.9 2006/07/25 21:29:04 debug Exp $
29   *   *
30   *  SH instructions.   *  SH instructions.
31   *   *
# Line 37  Line 37 
37    
38    
39  /*  /*
40   *  nop:  Do nothing.   *  nop: Nothing
41   */   */
42  X(nop)  X(nop)
43  {  {
44  }  }
45    
46    
47    /*
48     *  mov_rm_rn:  Copy rm into rn
49     *
50     *  arg[0] = ptr to rm
51     *  arg[1] = ptr to rn
52     */
53    X(mov_rm_rn)
54    {
55            reg(ic->arg[1]) = reg(ic->arg[0]);
56    }
57    
58    
59    /*
60     *  mov_imm_rn:  Set rn to an signed 8-bit value
61     *
62     *  arg[0] = int8_t imm, extended to at least int32_t
63     *  arg[1] = ptr to rn
64     */
65    X(mov_imm_rn)
66    {
67            reg(ic->arg[1]) = (int32_t)ic->arg[0];
68    }
69    
70    
71    /*
72     *  mov_l_disp_pc_rn:  Set rn to an immediate value relative to the current pc
73     *
74     *  arg[0] = offset from beginning of the current pc's page
75     *  arg[1] = ptr to rn
76     */
77    X(mov_l_disp_pc_rn)
78    {
79            reg(ic->arg[1]) = ic->arg[0] + (cpu->pc &
80                ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
81    }
82    
83    
84    /*
85     *  or_rm_rn:  rn = rn or rm
86     *
87     *  arg[0] = ptr to rm
88     *  arg[1] = ptr to rn
89     */
90    X(or_rm_rn)
91    {
92            reg(ic->arg[1]) |= reg(ic->arg[0]);
93    }
94    
95    
96    /*
97     *  shll_rn: Shift rn left by 1
98     *
99     *  arg[0] = ptr to rn
100     */
101    X(shll_rn)
102    {
103            uint32_t rn = reg(ic->arg[0]);
104            if (rn >> 31)
105                    cpu->cd.sh.sr |= SH_SR_T;
106            else
107                    cpu->cd.sh.sr &= ~SH_SR_T;
108            reg(ic->arg[0]) = rn << 1;
109    }
110    
111    
112    /*
113     *  stc_sr_rn: Store SR into Rn
114     *
115     *  arg[0] = ptr to rn
116     */
117    X(stc_sr_rn)
118    {
119            if (!(cpu->cd.sh.sr & SH_SR_MD)) {
120                    fatal("TODO: Throw RESINST exception, if MD = 0.\n");
121                    exit(1);
122            }
123    
124            reg(ic->arg[0]) = cpu->cd.sh.sr;
125    }
126    
127    
128    /*
129     *  ldc_rm_sr: Store Rm into SR
130     *
131     *  arg[0] = ptr to rm
132     */
133    X(ldc_rm_sr)
134    {
135            if (!(cpu->cd.sh.sr & SH_SR_MD)) {
136                    fatal("TODO: Throw RESINST exception, if MD = 0.\n");
137                    exit(1);
138            }
139    
140            sh_update_sr(cpu, reg(ic->arg[0]));
141    }
142    
143    
144  /*****************************************************************************/  /*****************************************************************************/
145    
146    
# Line 80  X(to_be_translated) Line 177  X(to_be_translated)
177          uint32_t iword;          uint32_t iword;
178          unsigned char *page;          unsigned char *page;
179          unsigned char ib[4];          unsigned char ib[4];
180          int main_opcode, instr_size = 4;          int main_opcode, isize = cpu->cd.sh.compact? 2 : sizeof(ib);
181          /* void (*samepage_function)(struct cpu *, struct sh_instr_call *);*/          int in_crosspage_delayslot = 0, r8, r4, lo4, lo8;
182            /*  void (*samepage_function)(struct cpu *, struct sh_instr_call *);  */
183    
184          /*  Figure out the (virtual) address of the instruction:  */          /*  Figure out the (virtual) address of the instruction:  */
185          if (cpu->cd.sh.compact) {          low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)
186                  instr_size = 2;              / sizeof(struct sh_instr_call);
187                  fatal("Compact: TODO\n");  
188                  exit(1);          /*  Special case for branch with delayslot on the next page:  */
189          } else {          if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
190                  low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)                  /*  fatal("[ delay-slot translation across page "
191                      / sizeof(struct sh_instr_call);                      "boundary ]\n");  */
192                  addr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1)                  in_crosspage_delayslot = 1;
                     << SH_INSTR_ALIGNMENT_SHIFT);  
                 addr += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);  
                 cpu->pc = addr;  
                 addr &= ~0x3;  
193          }          }
194    
195            addr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1)
196                << SH_INSTR_ALIGNMENT_SHIFT);
197            addr += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);
198            cpu->pc = (MODE_int_t)addr;
199            addr &= ~((1 << SH_INSTR_ALIGNMENT_SHIFT) - 1);
200    
201          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
202          page = cpu->cd.sh.host_load[addr >> 12];  #ifdef MODE32
203            page = cpu->cd.sh.host_load[(uint32_t)addr >> 12];
204    #else
205            {
206                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
207                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
208                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
209                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
210                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
211                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
212                        DYNTRANS_L3N)) & mask3;
213                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.sh.l1_64[x1];
214                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
215                    page = l3->host_load[x3];
216            }
217    #endif
218    
219          if (page != NULL) {          if (page != NULL) {
220                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT!\n");  */
221                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xfff), isize);
222          } else {          } else {
223                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS!\n");  */
224                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
225                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      isize, MEM_READ, CACHE_INSTRUCTION)) {
226                          fatal("to_be_translated(): "                          fatal("to_be_translated(): read failed: TODO\n");
                             "read failed: TODO\n");  
227                          goto bad;                          goto bad;
228                  }                  }
229          }          }
230    
231          iword = *((uint32_t *)&ib[0]);          iword = *((uint32_t *)&ib[0]);
232    
233  #ifdef HOST_LITTLE_ENDIAN          if (cpu->cd.sh.compact) {
234          iword = ((iword & 0xff) << 24) |                  if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
235                  ((iword & 0xff00) << 8) |                          iword = LE16_TO_HOST(iword);
236                  ((iword & 0xff0000) >> 8) |                  else
237                  ((iword & 0xff000000) >> 24);                          iword = BE16_TO_HOST(iword);
238  #endif                  main_opcode = iword >> 12;
239                    r8 = (iword >> 8) & 0xf;
240                    r4 = (iword >> 4) & 0xf;
241                    lo8 = iword & 0xff;
242                    lo4 = iword & 0xf;
243            } else {
244                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
245                            iword = LE32_TO_HOST(iword);
246                    else
247                            iword = BE32_TO_HOST(iword);
248                    main_opcode = -1;       /*  TODO  */
249                    fatal("SH5/SH64 isn't implemented yet. Sorry.\n");
250                    goto bad;
251            }
252    
253    
254  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
# Line 133  X(to_be_translated) Line 260  X(to_be_translated)
260           *  Translate the instruction:           *  Translate the instruction:
261           */           */
262    
         main_opcode = iword >> 26;  
   
263          switch (main_opcode) {          switch (main_opcode) {
264    
265          default:goto bad;          case 0x0:
266                    switch (lo8) {
267                    case 0x02:      /*  STC SR,Rn  */
268                            ic->f = instr(stc_sr_rn);
269                            ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
270                            break;
271                    case 0x09:      /*  NOP  */
272                            ic->f = instr(nop);
273                            if (iword & 0x0f00) {
274                                    fatal("Unimplemented NOP variant?\n");
275                                    goto bad;
276                            }
277                            break;
278                    default:fatal("Unimplemented opcode 0x%x,0x03%x\n",
279                                main_opcode, iword & 0xfff);
280                            goto bad;
281                    }
282                    break;
283    
284            case 0x2:
285                    switch (lo4) {
286                    case 0xb:       /*  OR Rm,Rn  */
287                            ic->f = instr(or_rm_rn);
288                            ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
289                            ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
290                            break;
291                    default:fatal("Unimplemented opcode 0x%x,0x%x\n",
292                                main_opcode, lo4);
293                            goto bad;
294                    }
295                    break;
296    
297            case 0x4:
298                    switch (lo8) {
299                    case 0x00:      /*  SHLL Rn  */
300                            ic->f = instr(shll_rn);
301                            ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
302                            break;
303                    case 0x0e:      /*  LDC Rm,SR  */
304                            ic->f = instr(ldc_rm_sr);
305                            ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
306                            break;
307                    default:fatal("Unimplemented opcode 0x%x,0x02%x\n",
308                                main_opcode, lo8);
309                            goto bad;
310                    }
311                    break;
312    
313            case 0x6:
314                    switch (lo4) {
315                    case 0x3:       /*  MOV Rm,Rn  */
316                            ic->f = instr(mov_rm_rn);
317                            ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
318                            ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
319                            break;
320                    default:fatal("Unimplemented opcode 0x%x,0x%x\n",
321                                main_opcode, lo4);
322                            goto bad;
323                    }
324                    break;
325    
326            case 0xd:       /*  MOV.L @(disp,PC),Rn  */
327                    ic->f = instr(mov_l_disp_pc_rn);
328                    ic->arg[0] = lo8 * 4 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
329                        << SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4;
330                    ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
331                    break;
332    
333            case 0xe:       /*  MOV #imm,Rn  */
334                    ic->f = instr(mov_imm_rn);
335                    ic->arg[0] = (int8_t)lo8;
336                    ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
337                    break;
338    
339            default:fatal("Unimplemented main opcode 0x%x\n", main_opcode);
340                    goto bad;
341          }          }
342    
343    

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

  ViewVC Help
Powered by ViewVC 1.1.26