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

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

revision 21 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 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_arm_coproc.c,v 1.15 2005/11/05 21:59:01 debug Exp $   *  $Id: cpu_arm_coproc.c,v 1.22 2006/02/17 18:38:30 debug Exp $
29   *   *
30   *  ARM coprocessor emulation.   *  ARM coprocessor emulation.
31   */   */
# Line 33  Line 33 
33  #include <stdio.h>  #include <stdio.h>
34  #include <stdlib.h>  #include <stdlib.h>
35  #include <string.h>  #include <string.h>
36    #include <unistd.h>
37  #include <ctype.h>  #include <ctype.h>
38    
39  #include "cpu.h"  #include "cpu.h"
40  #include "misc.h"  #include "misc.h"
41  #include "symbol.h"  #include "symbol.h"
42    
43    #include "i80321reg.h"
44    
45    
46  /*  /*
47   *  arm_coproc_15():   *  arm_coproc_15():
# Line 62  void arm_coproc_15(struct cpu *cpu, int Line 65  void arm_coproc_15(struct cpu *cpu, int
65    
66          switch (crn) {          switch (crn) {
67    
68          case 0: /*  Main ID register:  */          case 0: /*
69                  if (opcode2 != 0)                   *  Main ID register (and Cache Type register, on XScale)
70                          fatal("[ arm_coproc_15: TODO: cr0, opcode2=%i ]\n",                   *
71                     *  Writes are supposed to be ignored, according to Intel docs.
72                     */
73                    switch (opcode2) {
74                    case 0: if (l_bit)
75                                    cpu->cd.arm.r[rd] = cpu->cd.arm.cpu_type.cpu_id;
76                            else
77                                    fatal("[ arm_coproc_15: attempt to write "
78                                        "to the Main ID register? ]\n");
79                            break;
80                    case 1: if (l_bit)
81                                    cpu->cd.arm.r[rd] = cpu->cd.arm.cachetype;
82                            else
83                                    fatal("[ arm_coproc_15: attempt to write "
84                                        "to the Cache Type register? ]\n");
85                            break;
86                    default:fatal("[ arm_coproc_15: TODO: cr0, opcode2=%i ]\n",
87                              opcode2);                              opcode2);
88                  if (l_bit)                          exit(1);
89                          cpu->cd.arm.r[rd] = cpu->cd.arm.cpu_type.cpu_id;                  }
                 else  
                         fatal("[ arm_coproc_15: attempt to write to cr0? ]\n");  
90                  break;                  break;
91    
92          case 1: /*  Control Register:  */          case 1: /*  Control Register:  */
93                  if (l_bit) {                  if (l_bit) {
94                          cpu->cd.arm.r[rd] = cpu->cd.arm.control;                          /*  Load from the normal/aux control register:  */
95                            switch (opcode2) {
96                            case 0: cpu->cd.arm.r[rd] = cpu->cd.arm.control;
97                                    break;
98                            case 1: cpu->cd.arm.r[rd] = cpu->cd.arm.auxctrl;
99                                    break;
100                            default:fatal("Unimplemented opcode2 = %i\n", opcode2);
101                                    fatal("(opcode1=%i crn=%i crm=%i rd=%i l=%i)\n",
102                                        opcode1, crn, crm, rd, l_bit);
103                                    exit(1);
104                            }
105                            return;
106                    }
107    
108                    if (opcode2 == 1) {
109                            /*  Write to auxctrl:  */
110                            old_control = cpu->cd.arm.auxctrl;
111                            cpu->cd.arm.auxctrl = cpu->cd.arm.r[rd];
112                            if ((old_control & ARM_AUXCTRL_MD) !=
113                                (cpu->cd.arm.auxctrl & ARM_AUXCTRL_MD)) {
114                                    debug("[ setting the minidata cache attribute"
115                                        " to 0x%x ]\n", (cpu->cd.arm.auxctrl &
116                                        ARM_AUXCTRL_MD) >> ARM_AUXCTRL_MD_SHIFT);
117                            }
118                            if ((old_control & ARM_AUXCTRL_K) !=
119                                (cpu->cd.arm.auxctrl & ARM_AUXCTRL_K)) {
120                                    debug("[ %s write buffer coalescing ]\n",
121                                        cpu->cd.arm.auxctrl & ARM_AUXCTRL_K?
122                                        "Disabling" : "Enabling");
123                            }
124                          return;                          return;
125                    } else if (opcode2 != 0) {
126                            fatal("Unimplemented write, opcode2 = %i\n", opcode2);
127                            fatal("(opcode1=%i crn=%i crm=%i rd=%i l=%i)\n",
128                                opcode1, crn, crm, rd, l_bit);
129                            exit(1);
130                  }                  }
131                            
132                  /*                  /*
133                   *  Write to control:  Check each bit individually:                   *  Write to control:  Check each bit individually:
134                   */                   */
# Line 175  void arm_coproc_15(struct cpu *cpu, int Line 227  void arm_coproc_15(struct cpu *cpu, int
227                  break;                  break;
228    
229          case 9: /*  Cache lockdown:  */          case 9: /*  Cache lockdown:  */
230                    fatal("[ arm_coproc_15: cache lockdown: TODO ]\n");
231                  /*  TODO  */                  /*  TODO  */
232                  break;                  break;
233    
# Line 196  void arm_coproc_15(struct cpu *cpu, int Line 249  void arm_coproc_15(struct cpu *cpu, int
249                  }                  }
250                  break;                  break;
251    
252            /*  case 14:  */
253                    /*  Breakpoint registers on XScale (possibly others?)  */
254                    /*  TODO  */
255                    /*  break;  */
256    
257          case 15:/*  IMPLEMENTATION DEPENDENT!  */          case 15:/*  IMPLEMENTATION DEPENDENT!  */
258                  debug("[ arm_coproc_15: TODO: IMPLEMENTATION DEPENDENT! ]\n");                  switch (crm) {
259                    case 1: /*
260                             *  On XScale (and others? TODO), this is the
261                             *  CoProcessor Access Register.  Note/TODO: This isn't
262                             *  really used throughout the rest of the code yet.
263                             */
264                            if (l_bit)
265                                    cpu->cd.arm.r[rd] = cpu->cd.arm.cpar;
266                            else
267                                    cpu->cd.arm.cpar = cpu->cd.arm.r[rd];
268                            break;
269                    default:fatal("[ arm_coproc_15: TODO: IMPLEMENTATION "
270                                "DEPENDENT! ]\n");
271                            exit(1);
272                    }
273                  break;                  break;
274    
275          default:fatal("arm_coproc_15: unimplemented crn = %i\n", crn);          default:fatal("arm_coproc_15: unimplemented crn = %i\n", crn);
# Line 208  void arm_coproc_15(struct cpu *cpu, int Line 280  void arm_coproc_15(struct cpu *cpu, int
280  }  }
281    
282    
 /*****************************************************************************/  
   
   
283  /*  /*
284   *  arm_coproc_i80321():   *  arm_coproc_i80321_6():
285   *   *
286   *  Intel 80321 coprocessor.   *  Intel 80321 coprocessor 6.
287   */   */
288  void arm_coproc_i80321(struct cpu *cpu, int opcode1, int opcode2, int l_bit,  void arm_coproc_i80321_6(struct cpu *cpu, int opcode1, int opcode2, int l_bit,
289          int crn, int crm, int rd)          int crn, int crm, int rd)
290  {  {
291          switch (crm) {          switch (crm) {
292          case 0: fatal("[ 80321: crm 0: TODO ]\n");  
293            case 0: switch (crn) {
294                    case 0: if (l_bit)
295                                    cpu->cd.arm.r[rd] = cpu->cd.arm.i80321_inten;
296                            else
297                                    cpu->cd.arm.i80321_inten = cpu->cd.arm.r[rd];
298                            break;
299                    case 4: if (l_bit)
300                                    cpu->cd.arm.r[rd] = cpu->cd.arm.i80321_isteer;
301                            else {
302                                    cpu->cd.arm.i80321_isteer = cpu->cd.arm.r[rd];
303                                    if (cpu->cd.arm.r[rd] != 0) {
304                                            fatal("ARM xscale interrupt steering"
305                                                " is not yet implemented\n");
306                                            exit(1);
307                                    }
308                            }
309                            break;
310                    case 8: if (l_bit)
311                                    cpu->cd.arm.r[rd] = cpu->cd.arm.i80321_isrc;
312                            else {
313                                    cpu->cd.arm.i80321_isrc = cpu->cd.arm.r[rd];
314                                    fatal("TODO: XScale int ack?\n");
315                                    exit(1);
316                            }
317                            break;
318                    default:goto unknown;
319                    }
320                  break;                  break;
321          case 1: fatal("[ 80321: crm 1: TODO ]\n");  
322            case 1:
323    /* fatal("TIMER opcode1=%i opcode2=%i crn="
324        "%i crm=%i rd=%i l=%i)\n", opcode1, opcode2, crn, crm, rd, l_bit); */
325    
326                  switch (crn) {                  switch (crn) {
327                  case 0: /*  tmr0:  */                  case 0: /*  tmr0:  */
328                            if (l_bit)
329                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tmr0;
330                            else
331                                    cpu->cd.arm.tmr0 = cpu->cd.arm.r[rd];
332                            break;
333                    case 1: /*  tmr1:  */
334                            if (l_bit)
335                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tmr1;
336                            else
337                                    cpu->cd.arm.tmr1 = cpu->cd.arm.r[rd];
338                          break;                          break;
339                  case 2: /*  tcr0:  */                  case 2: /*  tcr0:  */
340                            if (l_bit) {
341                                    /*  NOTE/TODO: Ugly hack: timer increment  */
342                                    cpu->cd.arm.tcr0 ++;
343                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tcr0;
344                            } else {
345                                    cpu->cd.arm.tcr0 = cpu->cd.arm.r[rd];
346                            }
347                            break;
348                    case 3: /*  tcr1:  */
349                            if (l_bit) {
350                                    /*  NOTE/TODO: Ugly hack: timer increment  */
351                                    cpu->cd.arm.tcr1 ++;
352                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tcr1;
353                            } else {
354                                    cpu->cd.arm.tcr1 = cpu->cd.arm.r[rd];
355                            }
356                          break;                          break;
357                  case 4: /*  trr0:  */                  case 4: /*  trr0:  */
358                            if (l_bit)
359                                    cpu->cd.arm.r[rd] = cpu->cd.arm.trr0;
360                            else
361                                    cpu->cd.arm.trr0 = cpu->cd.arm.r[rd];
362                            break;
363                    case 5: /*  trr1:  */
364                            if (l_bit)
365                                    cpu->cd.arm.r[rd] = cpu->cd.arm.trr1;
366                            else
367                                    cpu->cd.arm.trr1 = cpu->cd.arm.r[rd];
368                          break;                          break;
369                  case 6: /*  tisr:  */                  case 6: /*  tisr:  */
370                            if (l_bit)
371                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tisr;
372                            else {
373                                    /*  Writing clears interrupts:  */
374                                    cpu->cd.arm.tisr &= ~cpu->cd.arm.r[rd];
375                                    if (!(cpu->cd.arm.tisr & TISR_TMR0))
376                                            cpu_interrupt_ack(cpu, 9);  /* TMR0 */
377                                    if (!(cpu->cd.arm.tisr & TISR_TMR1))
378                                            cpu_interrupt_ack(cpu, 10); /* TMR1 */
379                            }
380                          break;                          break;
381                  default:fatal("arm_coproc_i80321: unimplemented crn = %i\n",                  case 7: /*  wdtcr:  */
382                              crn);                          if (l_bit)
383                          fatal("(opcode1=%i opcode2=%i crm=%i rd=%i l=%i)\n",                                  cpu->cd.arm.r[rd] = cpu->cd.arm.wdtcr;
384                              opcode1, opcode2, crm, rd, l_bit);                          else
385                          exit(1);                                  cpu->cd.arm.wdtcr = cpu->cd.arm.r[rd];
386                            break;
387                    default:goto unknown;
388                  }                  }
389                  break;                  break;
390          default:fatal("arm_coproc_i80321: unimplemented opcode1=%i opcode2=%i"  
391                      " crn=%i crm=%i rd=%i l=%i)\n", opcode1, opcode2,          default:goto unknown;
                     crn, crm, rd, l_bit);  
                 exit(1);  
392          }          }
393    
394            return;
395    
396    unknown:
397            fatal("arm_coproc_i80321_6: unimplemented opcode1=%i opcode2=%i crn="
398                "%i crm=%i rd=%i l=%i)\n", opcode1, opcode2, crn, crm, rd, l_bit);
399            exit(1);
400  }  }
401    
402    
403  /*  /*
404   *  arm_coproc_i80321_14():   *  arm_coproc_xscale_14():
405   *   *
406   *  Intel 80321 coprocessor 14.   *  XScale coprocessor 14, Performance Monitoring Unit.
407   */   */
408  void arm_coproc_i80321_14(struct cpu *cpu, int opcode1, int opcode2, int l_bit,  void arm_coproc_xscale_14(struct cpu *cpu, int opcode1, int opcode2, int l_bit,
409          int crn, int crm, int rd)          int crn, int crm, int rd)
410  {  {
411            if (opcode2 != 0) {
412                    fatal("TODO: opcode2 = %i\n", opcode2);
413                    goto unknown;
414            }
415    
416          switch (crm) {          switch (crm) {
417          case 0: fatal("[ 80321_14: crm 0: TODO ]\n");  
418            case 0: switch (crn) {
419                    case 0: if (l_bit)
420                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_pmnc;
421                            else
422                                    cpu->cd.arm.xsc1_pmnc = cpu->cd.arm.r[rd];
423                            break;
424                    case 1: if (l_bit)
425                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_ccnt;
426                            else
427                                    cpu->cd.arm.xsc1_ccnt = cpu->cd.arm.r[rd];
428                            break;
429                    case 2: if (l_bit)
430                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_pmn0;
431                            else
432                                    cpu->cd.arm.xsc1_pmn0 = cpu->cd.arm.r[rd];
433                            break;
434                    case 3: if (l_bit)
435                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_pmn1;
436                            else
437                                    cpu->cd.arm.xsc1_pmn1 = cpu->cd.arm.r[rd];
438                            break;
439                    case 7: /*  UNIMPLEMENTED!!! TODO  */
440                            /*  Possibly some kind of idle or sleep function.  */
441                            break;
442                    default:goto unknown;
443                    }
444                  break;                  break;
445          default:fatal("arm_coproc_i80321_14: unimplemented opcode1=%i opcode2="  
446                      "%i crn=%i crm=%i rd=%i l=%i)\n", opcode1, opcode2,          case 1: switch (crn) {
447                      crn, crm, rd, l_bit);                  case 0: if (l_bit)
448                  exit(1);                                  cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmnc;
449                            else
450                                    cpu->cd.arm.xsc2_pmnc = cpu->cd.arm.r[rd];
451                            break;
452                    case 1: if (l_bit)
453                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_ccnt;
454                            else
455                                    cpu->cd.arm.xsc2_ccnt = cpu->cd.arm.r[rd];
456                            break;
457                    case 4: if (l_bit)
458                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_inten;
459                            else
460                                    cpu->cd.arm.xsc2_inten = cpu->cd.arm.r[rd];
461                            break;
462                    case 5: if (l_bit)
463                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_flag;
464                            else
465                                    cpu->cd.arm.xsc2_flag = cpu->cd.arm.r[rd];
466                            break;
467                    case 8: if (l_bit)
468                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_evtsel;
469                            else
470                                    cpu->cd.arm.xsc2_evtsel = cpu->cd.arm.r[rd];
471                            break;
472                    default:goto unknown;
473                    }
474                    break;
475    
476            case 2: switch (crn) {
477                    case 0: if (l_bit)
478                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn0;
479                            else
480                                    cpu->cd.arm.xsc2_pmn0 = cpu->cd.arm.r[rd];
481                            break;
482                    case 1: if (l_bit)
483                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn1;
484                            else
485                                    cpu->cd.arm.xsc2_pmn1 = cpu->cd.arm.r[rd];
486                            break;
487                    case 2: if (l_bit)
488                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn2;
489                            else
490                                    cpu->cd.arm.xsc2_pmn2 = cpu->cd.arm.r[rd];
491                            break;
492                    case 3: if (l_bit)
493                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn3;
494                            else
495                                    cpu->cd.arm.xsc2_pmn3 = cpu->cd.arm.r[rd];
496                            break;
497                    default:goto unknown;
498                    }
499                    break;
500    
501            default:goto unknown;
502          }          }
503    
504            return;
505    
506    unknown:
507            fatal("arm_coproc_xscale_14: unimplemented opcode1=%i opcode2="
508                "%i crn=%i crm=%i rd=%i l=%i)\n", opcode1, opcode2, crn,
509                crm, rd, l_bit);
510            exit(1);
511  }  }
512    

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

  ViewVC Help
Powered by ViewVC 1.1.26