- Main Page
- Related Pages
- Files

# avrcore.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: avrcore.c,v 1.87 2008/03/16 21:14:07 joerg_wunsch Exp $
    00003  *
    00004  ****************************************************************************
    00005  *
    00006  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
    00007  * Copyright (C) 2001, 2002, 2003, 2004  Theodore A. Roth
    00008  *
    00009  * This program is free software; you can redistribute it and/or modify
    00010  * it under the terms of the GNU General Public License as published by
    00011  * the Free Software Foundation; either version 2 of the License, or
    00012  * (at your option) any later version.
    00013  *
    00014  * This program is distributed in the hope that it will be useful,
    00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00017  * GNU General Public License for more details.
    00018  *
    00019  * You should have received a copy of the GNU General Public License
    00020  * along with this program; if not, write to the Free Software
    00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00022  *
    00023  ****************************************************************************
    00024  */
    00025
    00026 /**
    00027  *  \file avrcore.c
    00028  *  \brief Module for the core AvrCore object, which is the AVR CPU to be
    00029  *  simulated.
    00030  */
    00031
    00032 #include <config.h>
    00033
    00034 #include <stdio.h>
    00035 #include <stdlib.h>
    00036 #include <signal.h>
    00037
    00038 #include "avrerror.h"
    00039 #include "avrmalloc.h"
    00040 #include "avrclass.h"
    00041 #include "utils.h"
    00042 #include "callback.h"
    00043 #include "op_names.h"
    00044
    00045 #include "storage.h"
    00046 #include "flash.h"
    00047
    00048 #include "vdevs.h"
    00049 #include "memory.h"
    00050 #include "stack.h"
    00051 #include "register.h"
    00052 #include "sram.h"
    00053 #include "eeprom.h"
    00054 #include "ports.h"
    00055
    00056 #include "avrcore.h"
    00057
    00058 #include "display.h"
    00059 #include "decoder.h"
    00060 #include "sig.h"
    00061 #include "devsupp.h"
    00062
    00063 /** \brief Flag for enabling output of instruction debug messages. */
    00064 int global_debug_inst_output = 0;
    00065
    00066 /***************************************************************************\
    00067  *
    00068  * BreakPt(AvrClass) Methods
    00069  *
    00070 \***************************************************************************/
    00071
    00072 #ifndef DOXYGEN                 /* don't expose to doxygen */
    00073
    00074 typedef struct _BreakPt BreakPt;
    00075 struct _BreakPt
    00076 {
    00077     AvrClass parent;
    00078     int pc;
    00079     uint16_t opcode;
    00080 };
    00081
    00082 #endif
    00083
    00084 static BreakPt *brk_pt_new (int pc, uint16_t opcode);
    00085 static void brk_pt_construct (BreakPt *bp, int pc, uint16_t opcode);
    00086 static void brk_pt_destroy (void *bp);
    00087
    00088 static BreakPt *
    00089 brk_pt_new (int pc, uint16_t opcode)
    00090 {
    00091     BreakPt *bp;
    00092
    00093     bp = avr_new (BreakPt, 1);
    00094     brk_pt_construct (bp, pc, opcode);
    00095     class_overload_destroy ((AvrClass *)bp, brk_pt_destroy);
    00096
    00097     return bp;
    00098 }
    00099
    00100 static void
    00101 brk_pt_construct (BreakPt *bp, int pc, uint16_t opcode)
    00102 {
    00103     if (bp == NULL)
    00104         avr_error ("passed null ptr");
    00105
    00106     class_construct ((AvrClass *)bp);
    00107
    00108     bp->pc = pc;
    00109     bp->opcode = opcode;
    00110 }
    00111
    00112 static void
    00113 brk_pt_destroy (void *bp)
    00114 {
    00115     BreakPt *_bp = (BreakPt *)bp;
    00116
    00117     if (_bp == NULL)
    00118         return;
    00119
    00120     class_destroy (bp);
    00121 }
    00122
    00123 static DList *brk_pt_list_add (DList *head, int pc, uint16_t opcode);
    00124 static DList *brk_pt_list_delete (DList *head, int pc);
    00125 static BreakPt *brk_pt_list_lookup (DList *head, int pc);
    00126 static int brk_pt_cmp (AvrClass *d1, AvrClass *d2);
    00127
    00128 /* Compare function for break points. */
    00129
    00130 static int
    00131 brk_pt_cmp (AvrClass *d1, AvrClass *d2)
    00132 {
    00133     return ((BreakPt *)d1)->pc - ((BreakPt *)d2)->pc;
    00134 }
    00135
    00136 static DList *
    00137 brk_pt_list_add (DList *head, int pc, uint16_t opcode)
    00138 {
    00139     BreakPt *bp = brk_pt_new (pc, opcode);
    00140
    00141     return dlist_add (head, (AvrClass *)bp, brk_pt_cmp);
    00142 }
    00143
    00144 static DList *
    00145 brk_pt_list_delete (DList *head, int pc)
    00146 {
    00147     BreakPt *bp = brk_pt_new (pc, 0);
    00148
    00149     head = dlist_delete (head, (AvrClass *)bp, brk_pt_cmp);
    00150     class_unref ((AvrClass *)bp);
    00151
    00152     return head;
    00153 }
    00154
    00155 static BreakPt *
    00156 brk_pt_list_lookup (DList *head, int pc)
    00157 {
    00158     BreakPt *found;
    00159     BreakPt *bp = brk_pt_new (pc, 0);
    00160
    00161     found = (BreakPt *)dlist_lookup (head, (AvrClass *)bp, brk_pt_cmp);
    00162     class_unref ((AvrClass *)bp);
    00163
    00164     return found;
    00165 }
    00166
    00167 static DList *
    00168 brk_pt_iterator (DList *head, DListFP_Iter func, void *user_data)
    00169 {
    00170     return dlist_iterator (head, func, user_data);
    00171 }
    00172
    00173 /***************************************************************************\
    00174  *
    00175  * Irq(AvrClass) Methods: For managing the irq_pending list.
    00176  *
    00177 \***************************************************************************/
    00178
    00179 #ifndef DOXYGEN                 /* don't expose to doxygen */
    00180
    00181 typedef struct _Irq Irq;
    00182 struct _Irq
    00183 {
    00184     AvrClass parent;
    00185     IntVect *vector;
    00186
    00187     /* These are only used for storing lookup information. Copies of
    00188        core->{state,sleep_mode}. */
    00189     int state;
    00190     unsigned int sleep_mode;
    00191 };
    00192
    00193 #endif
    00194
    00195 static Irq *irq_new (IntVect *vector, int state,
    00196                             unsigned int sleep_mode);
    00197 static void irq_construct (Irq *irq, IntVect *vector, int state,
    00198                                   unsigned int sleep_mode);
    00199 static void irq_destroy (void *irq);
    00200
    00201 static Irq *
    00202 irq_new (IntVect *vector, int state, unsigned int sleep_mode)
    00203 {
    00204     Irq *irq;
    00205
    00206     irq = avr_new (Irq, 1);
    00207     irq_construct (irq, vector, state, sleep_mode);
    00208     class_overload_destroy ((AvrClass *)irq, irq_destroy);
    00209
    00210     return irq;
    00211 }
    00212
    00213 static void
    00214 irq_construct (Irq *irq, IntVect *vector, int state, unsigned int sleep_mode)
    00215 {
    00216     if (irq == NULL)
    00217         avr_error ("passed null ptr");
    00218
    00219     class_construct ((AvrClass *)irq);
    00220
    00221     irq->vector = vector;
    00222     irq->state = state;
    00223     irq->sleep_mode = sleep_mode;
    00224 }
    00225
    00226 static void
    00227 irq_destroy (void *irq)
    00228 {
    00229     Irq *_irq = (Irq *)irq;
    00230
    00231     if (_irq == NULL)
    00232         return;
    00233
    00234     class_destroy (irq);
    00235 }
    00236
    00237 static DList *irq_list_add (DList *head, IntVect *vector);
    00238 static DList *irq_list_delete (DList *head, IntVect *vector);
    00239 #if 0                           /* TRoth/2002-09-15: This isn't used. ??? */
    00240 static Irq *irq_list_lookup_addr (DList *head, IntVect *vector);
    00241 #endif
    00242 static int irq_cmp_addr (AvrClass *d1, AvrClass *d2);
    00243 static int irq_cmp_pending (AvrClass *d1, AvrClass *d2);
    00244
    00245 /* Compare function for break points. */
    00246
    00247 static int
    00248 irq_cmp_addr (AvrClass *d1, AvrClass *d2)
    00249 {
    00250     return ((Irq *)d1)->vector->addr - ((Irq *)d2)->vector->addr;
    00251 }
    00252
    00253 static DList *
    00254 irq_list_add (DList *head, IntVect *vector)
    00255 {
    00256     Irq *irq = irq_new (vector, 0, 0);
    00257
    00258     return dlist_add (head, (AvrClass *)irq, irq_cmp_addr);
    00259 }
    00260
    00261 static DList *
    00262 irq_list_delete (DList *head, IntVect *vector)
    00263 {
    00264     Irq *irq = irq_new (vector, 0, 0);
    00265
    00266     head = dlist_delete (head, (AvrClass *)irq, irq_cmp_addr);
    00267     class_unref ((AvrClass *)irq);
    00268
    00269     return head;
    00270 }
    00271
    00272 #if 0                           /* TRoth/2002-09-15: This isn't used. ??? */
    00273 static Irq *
    00274 irq_list_lookup_addr (DList *head, IntVect *vector)
    00275 {
    00276     Irq *found;
    00277     Irq *irq = irq_new (vector, 0, 0);
    00278
    00279     found = (Irq *)dlist_lookup (head, (AvrClass *)irq, irq_cmp_addr);
    00280     class_unref ((AvrClass *)irq);
    00281
    00282     return found;
    00283 }
    00284 #endif
    00285
    00286 static int
    00287 irq_cmp_pending (AvrClass *d1, AvrClass *d2)
    00288 {
    00289     Irq *i1 = (Irq *)d1;        /* This is the irq which might be ready to be
    00290                                    vectored into. */
    00291     int state = ((Irq *)d2)->state; /* The state the device is currently
    00292                                        in. */
    00293     unsigned int sleep_mode = ((Irq *)d2)->sleep_mode; /* This is the sleep
    00294                                                           mode the device in
    00295                                                           currently in. Only
    00296                                                           one bit should be
    00297                                                           set. */
    00298
    00299     if (state == STATE_SLEEP)
    00300     {
    00301         /* If device is in the sleep state, the irq will only pending if it
    00302            can wake up the device. */
    00303
    00304         if (sleep_mode & i1->vector->can_wake)
    00305             return 0;           /* vector into the irq */
    00306         else
    00307             return -1;          /* try the next irq */
    00308     }
    00309
    00310     /* If the state is not STATE_SLEEP, any irq we see is automatically
    00311        pending, so vector it. */
    00312
    00313     return 0;
    00314 }
    00315
    00316 /* Walk the list looking for a pending irq which can be handled. If the device
    00317    is in a sleep state, the can_wake mask could force the head of the list to
    00318    not be the irq which gets vectored. */
    00319
    00320 static IntVect *
    00321 irq_get_pending_vector (DList *head, int state, unsigned int sleep_mode)
    00322 {
    00323     Irq *found;
    00324     Irq *irq = irq_new (NULL, state, sleep_mode);
    00325
    00326     found = (Irq *)dlist_lookup (head, (AvrClass *)irq, irq_cmp_pending);
    00327     class_unref ((AvrClass *)irq);
    00328
    00329     return found->vector;
    00330 }
    00331
    00332 #if 0                           /* TRoth/2002-09-15: This isn't used. ??? */
    00333 static IntVect *
    00334 irq_get_head_vector (DList *head)
    00335 {
    00336     return ((Irq *)dlist_get_head_data (head))->vector;
    00337 }
    00338 #endif
    00339
    00340 /***************************************************************************\
    00341  *
    00342  * AvrCore(AvrClass) Methods
    00343  *
    00344 \***************************************************************************/
    00345
    00346 static void avr_core_construct (AvrCore *core, DevSuppDefn *dev);
    00347
    00348 /** \name AvrCore handling methods */
    00349
    00350 /*@{*/
    00351
    00352 /** \brief Allocate a new AvrCore object. */
    00353
    00354 AvrCore *
    00355 avr_core_new (char *dev_name)
    00356 {
    00357     AvrCore *core = NULL;
    00358     DevSuppDefn *dev = dev_supp_lookup_device (dev_name);
    00359
    00360     if (dev)
    00361     {
    00362         fprintf (stderr, "\nSimulating a %s device.\n\n", dev_name);
    00363
    00364         core = avr_new (AvrCore, 1);
    00365         avr_core_construct (core, dev);
    00366         class_overload_destroy ((AvrClass *)core, avr_core_destroy);
    00367     }
    00368
    00369     return core;
    00370 }
    00371
    00372 /** \brief Constructor for the AvrCore class. */
    00373
    00374 static void
    00375 avr_core_construct (AvrCore *core, DevSuppDefn *dev)
    00376 {
    00377     int flash_sz = dev_supp_get_flash_sz (dev);
    00378     int PC_sz = dev_supp_get_PC_sz (dev);
    00379     int stack_sz = dev_supp_get_stack_sz (dev);
    00380     int sram_sz = dev_supp_get_sram_sz (dev);
    00381     int xram_sz = dev_supp_get_xram_sz (dev);
    00382     int vtab_idx = dev_supp_get_vtab_idx (dev);
    00383     int xram_end, sram_end;
    00384     int addr;
    00385
    00386     if (core == NULL)
    00387         avr_error ("passed null ptr");
    00388
    00389     class_construct ((AvrClass *)core);
    00390
    00391     core->state = STATE_STOPPED;
    00392     core->sleep_mode = 0;       /* each bit represents a sleep mode */
    00393     core->PC = 0;
    00394     core->PC_size = PC_sz;
    00395     core->PC_max = flash_sz / 2; /* flash_sz is in bytes, need number of
    00396                                     words here */
    00397
    00398     core->flash = flash_new (flash_sz);
    00399
    00400     core->breakpoints = NULL;
    00401
    00402     core->irq_pending = NULL;
    00403     core->irq_vtable = (IntVect *)(global_vtable_list[vtab_idx]);
    00404     core->irq_offset = 0;
    00405
    00406     core->CK = 0;
    00407     core->inst_CKS = 0;
    00408
    00409     core->clk_cb = NULL;
    00410     core->async_cb = NULL;
    00411
    00412     /* FIXME: hack to get it to compile. */
    00413     if (dev_supp_has_ext_io_reg (dev))
    00414         sram_end = 0xff + sram_sz;
    00415     else
    00416         sram_end = 0x5f + sram_sz;
    00417     if (xram_sz)
    00418         xram_end = 0xffff;
    00419     else
    00420         xram_end = sram_end;    /* i.e., no XRAM at all */
    00421     if (dev_supp_has_ext_io_reg (dev))
    00422         core->mem = mem_new (0x1f, 0xff, sram_end, xram_end);
    00423     else
    00424         core->mem = mem_new (0x1f, 0x5f, sram_end, xram_end);
    00425
    00426     /* Attach the gpwr's to the memory bus. */
    00427
    00428     core->gpwr = gpwr_new ();
    00429     for (addr = 0; addr < 0x20; addr++)
    00430     {
    00431         static char *reg_name[] = { "r00", "r01", "r02", "r03", "r04", "r05",
    00432                                     "r06", "r07", "r08", "r09", "r10", "r11",
    00433                                     "r12", "r13", "r14", "r15", "r16", "r17",
    00434                                     "r18", "r19", "r20", "r21", "r22", "r23",
    00435                                     "r24", "r25", "r26", "r27", "r28", "r29",
    00436                                     "r30", "r31" };
    00437
    00438         avr_core_attach_vdev (core, addr, reg_name[addr],
    00439                               (VDevice *)core->gpwr, 0, 0, 0xff, 0xff);
    00440     }
    00441
    00442     dev_supp_attach_io_regs (core, dev);
    00443
    00444     /* Set up the stack. */
    00445
    00446     if (stack_sz)
    00447     {
    00448         core->stack = (Stack *)hwstack_new (stack_sz);
    00449     }
    00450     else
    00451     {
    00452         /* Assuming that SPL is always at 0x5d. */
    00453
    00454         core->stack = (Stack *)memstack_new (core->mem, 0x5d);
    00455     }
    00456
    00457     /* Assuming the SREG is always at 0x5f. */
    00458
    00459     core->sreg = (SREG *)avr_core_get_vdev_by_addr (core, 0x5f);
    00460     class_ref ((AvrClass *)core->sreg);
    00461
    00462     /* Assuming that RAMPZ is always at 0x5b. If the device doesn't support
    00463        RAMPZ, install a NULL pointer. */
    00464
    00465     core->rampz = (RAMPZ *)avr_core_get_vdev_by_addr (core, 0x5b);
    00466     if (core->rampz)
    00467         class_ref ((AvrClass *)core->rampz);
    00468
    00469     /* Attach the internal sram to the memory bus if needed. */
    00470
    00471     if (sram_sz)
    00472     {
    00473         int base;
    00474         VDevice *sram;
    00475
    00476         if (dev_supp_has_ext_io_reg (dev))
    00477             base = SRAM_EXTENDED_IO_BASE;
    00478         else
    00479             base = SRAM_BASE;
    00480
    00481         core->sram = sram_new (base, sram_sz);
    00482         sram = (VDevice *)core->sram;
    00483
    00484         avr_message ("attach: Internal SRAM from 0x%04x to 0x%04x\n", base,
    00485                      (base + sram_sz - 1));
    00486
    00487         for (addr = base; addr < (base + sram_sz); addr++)
    00488         {
    00489             avr_core_attach_vdev (core, addr, "Internal SRAM", sram, 0, 0,
    00490                                   0xff, 0xff);
    00491         }
    00492     }
    00493     else
    00494     {
    00495         core->sram = NULL;
    00496     }
    00497
    00498     if (xram_sz)
    00499     {
    00500         int base;
    00501         VDevice *xram;
    00502
    00503         if (dev_supp_has_ext_io_reg (dev))
    00504             base = SRAM_EXTENDED_IO_BASE + sram_sz;
    00505         else
    00506             base = SRAM_BASE + sram_sz;
    00507
    00508         core->xram = sram_new (base, xram_sz);
    00509         xram = (VDevice *)core->xram;
    00510
    00511         avr_message ("attach: External SRAM from 0x%04x to 0x%04x\n", base,
    00512                      (base + xram_sz - 1));
    00513
    00514         for (addr = base; addr < (base + xram_sz); addr++)
    00515         {
    00516             avr_core_attach_vdev (core, addr, "External SRAM", xram, 0, 0,
    00517                                   0xff, 0xff);
    00518         }
    00519     }
    00520     else
    00521     {
    00522         core->xram = NULL;
    00523     }
    00524
    00525     core->eeprom = NULL;
    00526
    00527     /* Initialize the decoder lookup table */
    00528
    00529     decode_init_lookup_table ();
    00530 }
    00531
    00532 /**
    00533  * \brief Destructor for the AvrCore class.
    00534  *
    00535  * Not to be called directly, except by a derived class.
    00536  * Called via class_unref.
    00537  */
    00538 void
    00539 avr_core_destroy (void *core)
    00540 {
    00541     AvrCore *_core = (AvrCore *)core;
    00542
    00543     if (_core == NULL)
    00544         return;
    00545
    00546     class_unref ((AvrClass *)_core->sreg);
    00547     class_unref ((AvrClass *)_core->flash);
    00548     class_unref ((AvrClass *)_core->gpwr);
    00549     class_unref ((AvrClass *)_core->mem);
    00550     class_unref ((AvrClass *)_core->stack);
    00551
    00552     dlist_delete_all (_core->breakpoints);
    00553     dlist_delete_all (_core->clk_cb);
    00554     dlist_delete_all (_core->async_cb);
    00555     dlist_delete_all (_core->irq_pending);
    00556
    00557     class_destroy (core);
    00558 }
    00559
    00560 /** \brief Query the sizes of the 3 memory spaces: flash, sram, and eeprom. */
    00561 void
    00562 avr_core_get_sizes (AvrCore *core, int *flash, int *sram, int *sram_start,
    00563                     int *eeprom)
    00564 {
    00565     *flash = flash_get_size (core->flash);
    00566
    00567     if (core->sram)
    00568     {
    00569         *sram = sram_get_size (core->sram);
    00570         *sram_start = sram_get_base (core->sram);
    00571     }
    00572     else
    00573     {
    00574         *sram = 0;
    00575         *sram_start = 0;
    00576     }
    00577
    00578     if (core->eeprom)
    00579         *eeprom = eeprom_get_size (core->eeprom);
    00580     else
    00581         *eeprom = 0;
    00582 }
    00583
    00584 /** \brief Attach a virtual device into the Memory. */
    00585 extern inline void avr_core_attach_vdev (AvrCore *core, uint16_t addr,
    00586                                          char *name, VDevice *vdev,
    00587                                          int flags, uint8_t reset_value,
    00588                                          uint8_t rd_mask, uint8_t wr_mask);
    00589
    00590 /** \brief Returns the \c VDevice with the name \a name. */
    00591 extern inline VDevice *avr_core_get_vdev_by_name (AvrCore *core, char *name);
    00592
    00593 /** \brief Returns the \c VDevice which handles the address \a addr. */
    00594 extern inline VDevice *avr_core_get_vdev_by_addr (AvrCore *core, int addr);
    00595
    00596 /** \brief Sets the device's state (running, stopped, breakpoint, sleep). */
    00597 extern inline void avr_core_set_state (AvrCore *core, StateType state);
    00598
    00599 /** \brief Returns the device's state (running, stopped, breakpoint, sleep). */
    00600 extern inline int avr_core_get_state (AvrCore *core);
    00601
    00602 /** \brief Sets the device to a sleep state.
    00603   * \param core Pointer to the core.
    00604   * \param sleep_mode The BITNUMBER of the sleepstate.
    00605   */
    00606 extern inline void avr_core_set_sleep_mode (AvrCore *core, int sleep_mode);
    00607
    00608 /** \brief Return the device's sleepmode. */
    00609 extern inline int avr_core_get_sleep_mode (AvrCore *core);
    00610
    00611 /*@}*/
    00612
    00613 /** \name Program Memory Space Access Methods */
    00614
    00615 /*@{*/
    00616
    00617 /** \brief Reads a word from flash memory. */
    00618 static uint16_t avr_core_flash_read (AvrCore *core, int addr);
    00619
    00620 /** \brief Writes a word to flash memory. */
    00621 static void avr_core_flash_write (AvrCore *core, int addr,
    00622                                          uint16_t val);
    00623
    00624 /** \brief Writes a byte to flash memory.
    00625   *
    00626   * This function writes the lower 8 bit of a flash word.
    00627   * Use avr_core_flash_write() write to write a full word,
    00628   * or avr_core_flash_write_hi8() to write the upper 8 bits.
    00629   */
    00630 static void avr_core_flash_write_lo8 (AvrCore *core, int addr,
    00631                                              uint8_t val);
    00632
    00633 /** \brief Writes a byte to flash memory.
    00634   *
    00635   * This function writes the upper 8 bit of a flash word.
    00636   * Use avr_core_flash_write() write to write a full word,
    00637   * or avr_core_flash_write_lo8() to write the lower 8 bits.
    00638   */
    00639 static void avr_core_flash_write_hi8 (AvrCore *core, int addr,
    00640                                              uint8_t val);
    00641
    00642 /*@}*/
    00643
    00644 /** \name Data Memory Space Access Methods */
    00645
    00646 /*@{*/
    00647
    00648 /** \brief Reads a byte from memory.
    00649   *
    00650   * This accesses the \a register \a file and the \a SRAM.
    00651   */
    00652 static uint8_t avr_core_mem_read (AvrCore *core, int addr);
    00653
    00654 /** \brief Writes a byte to memory.
    00655   *
    00656   * This accesses the \a register \a file and the \a SRAM.
    00657   */
    00658 static void avr_core_mem_write (AvrCore *core, int addr, uint8_t val);
    00659
    00660 /*@}*/
    00661
    00662 /** \name Status Register Access Methods */
    00663
    00664 /*@{*/
    00665
    00666 /** \brief Get the value of the status register. */
    00667
    00668 static uint8_t avr_core_sreg_get (AvrCore *core);
    00669
    00670 /** \brief Set the value of the status register. */
    00671
    00672 static void avr_core_sreg_set (AvrCore *core, uint8_t v);
    00673
    00674 /** \brief Get the value of bit \c b of the status register. */
    00675
    00676 extern inline int avr_core_sreg_get_bit (AvrCore *core, int b);
    00677
    00678 /** \brief Set the value of bit \c b of the status register. */
    00679
    00680 extern inline void avr_core_sreg_set_bit (AvrCore *core, int b, int v);
    00681
    00682 /*@}*/
    00683
    00684 /** \name RAMPZ access methods */
    00685
    00686 /*@{*/
    00687
    00688 /** \brief Get the value of the rampz register. */
    00689
    00690 extern inline uint8_t avr_core_rampz_get (AvrCore *core);
    00691
    00692 /** \brief Set the value of the rampz register. */
    00693
    00694 extern inline void avr_core_rampz_set (AvrCore *core, uint8_t v);
    00695
    00696 /*@}*/
    00697
    00698 /**
    00699  * \Name General Purpose Working Register Access Methods
    00700  */
    00701
    00702 /*@{*/
    00703
    00704 /** \brief Returns a GPWR's(\a r0-r31) value. */
    00705 static uint8_t avr_core_gpwr_get (AvrCore *core, int reg);
    00706
    00707 /** \brief Writes a GPWR's (\a r0-r31) value. */
    00708 static void avr_core_gpwr_set (AvrCore *core, int reg, uint8_t val);
    00709
    00710 /*@}*/
    00711
    00712 /**
    00713  * \name Direct I/O Register Access Methods
    00714  *
    00715  * IO Registers are mapped in memory directly after the 32 (0x20)
    00716  * general registers.
    00717  */
    00718
    00719 /*@{*/
    00720
    00721 /** \brief Displays all registers. */
    00722 void
    00723 avr_core_io_display_names (AvrCore *core)
    00724 {
    00725     int i;
    00726     uint8_t val;
    00727     char name[80];
    00728
    00729     for (i = IO_REG_ADDR_BEGIN; i < IO_REG_ADDR_END; i++)
    00730     {
    00731         mem_io_fetch (core->mem, i, &val, name, sizeof (name) - 1);
    00732         display_io_reg_name (i - IO_REG_ADDR_BEGIN, name);
    00733     }
    00734 }
    00735
    00736 /** \brief Reads the value of a register.
    00737   * \param core Pointer to the core.
    00738   * \param reg The registers address. This address is counted above the
    00739   *  beginning of the registers memory block (0x20).
    00740   */
    00741 extern inline uint8_t avr_core_io_read (AvrCore *core, int reg);
    00742
    00743 /** \brief Writes the value of a register.
    00744   * See avr_core_io_read() for a discussion of \a reg. */
    00745 extern inline void avr_core_io_write (AvrCore *core, int reg, uint8_t val);
    00746
    00747 /** \brief Read an io register into val and put the name of the register into
    00748   * buf. */
    00749 static void avr_core_io_fetch (AvrCore *core, int reg, uint8_t * val,
    00750                                       char *buf, int bufsiz);
    00751
    00752 /*@}*/
    00753
    00754 /** \name Stack Methods */
    00755
    00756 /*@{*/
    00757
    00758 /** \brief Pop 1-4 bytes off of the stack.
    00759  *
    00760  * See stack_pop() for more details.
    00761  */
    00762 extern inline uint32_t avr_core_stack_pop (AvrCore *core, int bytes);
    00763
    00764 /** \brief Push 1-4 bytes onto the stack.
    00765  *
    00766  * See stack_push() for more details.
    00767  */
    00768 extern inline void avr_core_stack_push (AvrCore *core, int bytes,
    00769                                         uint32_t val);
    00770
    00771 /*@}*/
    00772
    00773 /** \name Program Counter Methods */
    00774
    00775 /*@{*/
    00776
    00777 /** \brief Returns the size of the Program Counter in bytes.
    00778  *
    00779  * Most devices have a 16-bit PC (2 bytes), but some larger ones
    00780  * (e.g. mega256), have a 22-bit PC (3 bytes).
    00781  */
    00782 extern inline int32_t avr_core_PC_size (AvrCore *core);
    00783
    00784 /** \brief Returns the maximum value of the Program Counter.
    00785  *
    00786  * This is flash_size / 2.
    00787  */
    00788 static int32_t avr_core_PC_max (AvrCore *core);
    00789
    00790 /** \brief Return the current of the Program Counter. */
    00791 static int32_t avr_core_PC_get (AvrCore *core);
    00792
    00793 /** \brief Set the Program Counter to val.
    00794  *
    00795  * If val is not in the valid range of PC values, it is adjusted to fall in
    00796  * the valid range.
    00797  */
    00798 static void avr_core_PC_set (AvrCore *core, int32_t val);
    00799
    00800 /** \brief Increment the Program Counter by val.
    00801  *
    00802  * val can be either positive or negative.
    00803  *
    00804  * If the result of the incrememt is outside the valid range for PC, it is
    00805  * adjusted to fall in the valid range. This allows addresses to wrap around
    00806  * the end of the insn space.
    00807  */
    00808 extern inline void avr_core_PC_incr (AvrCore *core, int val);
    00809
    00810 /*@}*/
    00811
    00812 /** \name Methods for accessing CK and instruction Clocks */
    00813
    00814 /*@{*/
    00815
    00816 /** \brief Get the current clock counter. */
    00817 extern inline uint64_t avr_core_CK_get (AvrCore *core);
    00818
    00819 /** \brief Increment the clock counter. */
    00820 extern inline void avr_core_CK_incr (AvrCore *core);
    00821
    00822 /** \brief Get the number of clock cycles remaining for the currently
    00823  *  executing instruction. */
    00824 extern inline int avr_core_inst_CKS_get (AvrCore *core);
    00825
    00826 /** \brief Set the number of clock cycles for the instruction being
    00827  *  executed. */
    00828 extern inline void avr_core_inst_CKS_set (AvrCore *core, int val);
    00829
    00830 /** \name Interrupt Access Methods. */
    00831
    00832 /*@{*/
    00833
    00834 /** \brief Gets the first pending irq. */
    00835 IntVect *
    00836 avr_core_irq_get_pending (AvrCore *core)
    00837 {
    00838     return irq_get_pending_vector (core->irq_pending, core->state,
    00839                                    core->sleep_mode);
    00840 }
    00841
    00842 /** \brief Raises an irq by adding it's data to the irq_pending list. */
    00843 void
    00844 avr_core_irq_raise (AvrCore *core, unsigned int irq)
    00845 {
    00846     IntVect *irq_ptr = &core->irq_vtable[irq];
    00847
    00848 #if !defined(DISABLE_IRQ_MESSAGES)
    00849     avr_message ("Raising irq # %u [%s at 0x%x]\n", irq, irq_ptr->name,
    00850                  irq_ptr->addr * 2);
    00851 #endif
    00852     core->irq_pending = irq_list_add (core->irq_pending, irq_ptr);
    00853 }
    00854
    00855 /** \brief Calls the interrupt's callback to clear the flag. */
    00856 void
    00857 avr_core_irq_clear (AvrCore *core, IntVect *irq)
    00858 {
    00859     core->irq_pending = irq_list_delete (core->irq_pending, irq);
    00860 }
    00861
    00862 /** \brief Removes all irqs from the irq_pending list. */
    00863 extern inline void avr_core_irq_clear_all (AvrCore *core);
    00864
    00865 /*@}*/
    00866
    00867 /** \name Break point access methods. */
    00868
    00869 /*@{*/
    00870
    00871 /** \brief Inserts a break point. */
    00872
    00873 void
    00874 avr_core_insert_breakpoint (AvrCore *core, int pc)
    00875 {
    00876 #define BREAK_OPCODE 0x9598
    00877
    00878     uint16_t insn = flash_read (core->flash, pc);
    00879
    00880     core->breakpoints = brk_pt_list_add (core->breakpoints, pc, insn);
    00881
    00882     flash_write (core->flash, pc, BREAK_OPCODE);
    00883 }
    00884
    00885 /** \brief Removes a break point. */
    00886
    00887 void
    00888 avr_core_remove_breakpoint (AvrCore *core, int pc)
    00889 {
    00890     BreakPt *bp;
    00891
    00892     bp = brk_pt_list_lookup (core->breakpoints, pc);
    00893     if (bp)
    00894     {
    00895         uint16_t insn = bp->opcode;
    00896
    00897         core->breakpoints = brk_pt_list_delete (core->breakpoints, pc);
    00898
    00899         flash_write (core->flash, pc, insn);
    00900     }
    00901 }
    00902
    00903 #ifndef DOXYGEN                 /* don't expose to doxygen */
    00904
    00905 struct bp_enable_data
    00906 {
    00907     AvrCore *core;
    00908     int enable;
    00909 };
    00910
    00911 #endif /* DOXYGEN */
    00912
    00913 static int
    00914 iter_enable_breakpoint (AvrClass *data, void *user_data)
    00915 {
    00916     BreakPt *bp = (BreakPt *)data;
    00917     struct bp_enable_data *bed = (struct bp_enable_data *)user_data;
    00918
    00919     if (bed->enable)
    00920     {
    00921         uint16_t insn = flash_read (bed->core->flash, bp->pc);
    00922
    00923         if (insn != BREAK_OPCODE)
    00924         {
    00925             /* Enable the breakpoint */
    00926             bp->opcode = insn;
    00927             flash_write (bed->core->flash, bp->pc, BREAK_OPCODE);
    00928         }
    00929     }
    00930     else
    00931     {
    00932         /* Disable the breakpoint */
    00933         flash_write (bed->core->flash, bp->pc, bp->opcode);
    00934     }
    00935
    00936     return 0;                   /* Don't delete any item from the list. */
    00937 }
    00938
    00939 /** \brief Disable breakpoints.
    00940
    00941     Disables all breakpoints that where set using avr_core_insert_breakpoint().
    00942     The breakpoints are not removed from the breakpoint list.  */
    00943
    00944 void
    00945 avr_core_disable_breakpoints (AvrCore *core)
    00946 {
    00947     struct bp_enable_data bed = { core, 0 };
    00948
    00949     core->breakpoints =
    00950         brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed);
    00951 }
    00952
    00953 /** \brief Enable breakpoints.
    00954
    00955     Enables all breakpoints that where previous disabled. */
    00956
    00957 void
    00958 avr_core_enable_breakpoints (AvrCore *core)
    00959 {
    00960     struct bp_enable_data bed = { core, 1 };
    00961
    00962     core->breakpoints =
    00963         brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed);
    00964 }
    00965
    00966 /*@}*/
    00967
    00968 /* Private
    00969
    00970    Execute an instruction.
    00971    Presets the number of instruction clocks to zero so that break points and
    00972    invalid opcodes don't add extraneous clock counts.
    00973
    00974    Also checks for software breakpoints.
    00975    Any opcode except 0xffff can be a breakpoint.
    00976
    00977    Returns BREAK_POINT, or >= 0. */
    00978
    00979 static int
    00980 exec_next_instruction (AvrCore *core)
    00981 {
    00982     int result, pc;
    00983     uint16_t opcode;
    00984     struct opcode_info *opi;
    00985
    00986     pc = avr_core_PC_get (core);
    00987     opcode = flash_read (core->flash, pc);
    00988
    00989     /* Preset the number of instruction clocks to zero so that break points
    00990        and invalid opcodes don't add extraneous clock counts. */
    00991     avr_core_inst_CKS_set (core, 0);
    00992
    00993     opi = decode_opcode (opcode);
    00994
    00995     result = opi->func (core, opcode, opi->arg1, opi->arg2);
    00996
    00997     if (global_debug_inst_output)
    00998         fprintf (stderr, "0x%06x (0x%06x) : 0x%04x : %s\n", pc, pc * 2,
    00999                  opcode, global_opcode_name[result]);
    01000
    01001     return result;
    01002 }
    01003
    01004 /** \name Program control methods */
    01005
    01006 /*@{*/
    01007
    01008 /*
    01009  * Private
    01010  *
    01011  * Checks to see if an interrupt is pending. If any are pending, and
    01012  * if SREG(I) is set, the following will occur:
    01013  *   - push current PC onto stack
    01014  *   - PC <- interrupt vector
    01015  *   - I flag of SREG is cleared
    01016  *
    01017  * Reset vector is not controlled by the SREG(I) flag, thus if reset
    01018  * interrupt has occurred, the device will be reset irregardless of state
    01019  * of SREG(I).
    01020  *
    01021  * \note There are different ways of doing this:
    01022  * - In register.c  wdtcr_intr_cb() we can directly reset the MCU without
    01023  *   the use of irqs. This would require to make the callback an async
    01024  *   callback and it would allow the speed improvments commented out below
    01025  *   to be activated.
    01026  * - Keep it as an interrupt an waste CPU time.
    01027  *
    01028  * Ted, what do you think we should do?
    01029  */
    01030
    01031 static void
    01032 avr_core_check_interrupts (AvrCore *core)
    01033 {
    01034     IntVect *irq;
    01035
    01036     if (core->irq_pending)
    01037     {
    01038         irq = avr_core_irq_get_pending (core);
    01039
    01040         if (irq)
    01041         {
    01042             if (irq->name == NULL)
    01043             {
    01044                 avr_error ("Raised an invalid irq for device");
    01045             }
    01046
    01047             if (irq->addr == IRQ_RESET_ADDR)
    01048             {
    01049                 /* The global interrupt (SREG.I) never blocks a reset. We
    01050                    don't need to clear the irq since a reset clears all
    01051                    pending irq's. */
    01052                 avr_core_reset (core);
    01053             }
    01054
    01055             if (avr_core_sreg_get_bit (core, SREG_I))
    01056             {
    01057                 int pc = avr_core_PC_get (core);
    01058                 int pc_bytes = avr_core_PC_size (core);
    01059
    01060                 avr_core_stack_push (core, pc_bytes, pc);
    01061                 avr_core_sreg_set_bit (core, SREG_I, 0);
    01062
    01063 #if !defined(DISABLE_IRQ_MESSAGES)
    01064                 avr_message ("Vectoring to irq at addr:0x%x offset:0x%x\n",
    01065                              irq->addr * 2, core->irq_offset * 2);
    01066 #endif
    01067
    01068                 avr_core_PC_set (core, irq->addr + core->irq_offset);
    01069
    01070                 avr_core_irq_clear (core, irq);
    01071             }
    01072         }
    01073     }
    01074 }
    01075
    01076 /**
    01077  * \brief Process a single program instruction, all side effects and
    01078  * peripheral stimulii.
    01079  *
    01080  * Executes instructions, calls callbacks, and checks for interrupts.  */
    01081
    01082 int
    01083 avr_core_step (AvrCore *core)
    01084 {
    01085     int res = 0;
    01086     int state;
    01087
    01088     /* The MCU is stopped when in one of the many sleep modes */
    01089     state = avr_core_get_state (core);
    01090     if (state != STATE_SLEEP)
    01091     {
    01092         /* execute an instruction; may change state */
    01093         res = exec_next_instruction (core);
    01094     }
    01095
    01096     /* Execute the clock callbacks */
    01097     while (core->inst_CKS > 0)
    01098     {
    01099         /* propagate clocks here */
    01100         avr_core_clk_cb_exec (core);
    01101
    01102         avr_core_CK_incr (core);
    01103
    01104         core->inst_CKS--;
    01105     }
    01106
    01107     /* FIXME: async cb's and interrupt checking might need to be put
    01108        somewhere else. */
    01109
    01110     /* Execute the asynchronous callbacks */
    01111     avr_core_async_cb_exec (core);
    01112
    01113     /* Check interrupts here. If the previous instruction was a reti, then we
    01114        need to delay handling of any pending IRQs until after the next
    01115        instruction is executed. */
    01116     if (res != opcode_RETI)
    01117         avr_core_check_interrupts (core);
    01118
    01119     return res;
    01120 }
    01121
    01122 /** \brief Start the processing of instructions by the simulator.
    01123  *
    01124  * The simulated device will run until one of the following occurs:
    01125  *   - The state of the core is no longer STATE_RUNNING.
    01126  *   - The simulator receives a SIGINT signal.
    01127  *   - A breakpoint is reached (currently causes core to stop running).
    01128  *   - A fatal internal error occurs.
    01129  *
    01130  * \note When running simulavr in gdb server mode, this function is not
    01131  * used. The avr_core_step() function is called repeatedly in a loop when the
    01132  * continue command is issued from gdb. As such, the functionality in this
    01133  * loop should be kept to a minimum.
    01134  *
    01135  * \todo Should add some basic breakpoint handling here. Maybe allow
    01136  * continuing, and simple breakpoint management (disable, delete, set)
    01137  */
    01138
    01139 void
    01140 avr_core_run (AvrCore *core)
    01141 {
    01142     uint64_t cnt = 0;
    01143     int res;
    01144     uint64_t start_time, run_time;
    01145
    01146     avr_core_reset (core);      /* make sure the device is in a sane state. */
    01147
    01148     core->state = STATE_RUNNING;
    01149
    01150     signal_watch_start (SIGINT);
    01151
    01152     /* FIXME: [TRoth 2002/03/19] This loop isn't going to handle sleep or idle
    01153        modes properly. */
    01154
    01155     start_time = get_program_time ();
    01156     while (core->state == STATE_RUNNING)
    01157     {
    01158         if (signal_has_occurred (SIGINT))
    01159             break;
    01160
    01161         res = avr_core_step (core);
    01162
    01163         if (res == BREAK_POINT)
    01164             break;
    01165
    01166         cnt++;
    01167     }
    01168     run_time = get_program_time () - start_time;
    01169
    01170     signal_watch_stop (SIGINT);
    01171
    01172     /* avoid division by zero below */
    01173     if (run_time == 0) run_time = 1;
    01174
    01175     avr_message ("Run time was %lld.%03lld seconds.\n", run_time / 1000,
    01176                  run_time % 1000);
    01177
    01178     if (run_time == 0)
    01179          run_time = 1;          /* Avoid division by zero. */
    01180
    01181     avr_message ("Executed %lld instructions.\n", cnt);
    01182     avr_message ("   %lld insns/sec\n", (cnt * 1000) / run_time);
    01183     avr_message ("Executed %lld clock cycles.\n", avr_core_CK_get (core));
    01184     avr_message ("   %lld clks/sec\n",
    01185                  (avr_core_CK_get (core) * 1000) / run_time);
    01186 }
    01187
    01188 /** \brief Sets the simulated CPU back to its initial state.
    01189  *
    01190  *  Zeroes out PC, IRQ's, clock, and memory.
    01191  */
    01192
    01193 void
    01194 avr_core_reset (AvrCore *core)
    01195 {
    01196     avr_core_PC_set (core, 0);
    01197     avr_core_irq_clear_all (core);
    01198
    01199     avr_core_inst_CKS_set (core, 0);
    01200
    01201     /* Send clock cycles to display.
    01202        Normaly the clockcycles must not be reset here!
    01203        This leads to an error in the vcd file. */
    01204
    01205     display_clock (core->CK);
    01206
    01207     mem_reset (core->mem);
    01208 }
    01209
    01210 /*@}*/
    01211
    01212 /** \name Callback Handling Methods */
    01213
    01214 /*@{*/
    01215
    01216 /**
    01217  * \brief For adding external read and write callback functions.
    01218  *
    01219  * rd and wr should come in pairs, but it is safe to add
    01220  * empty function via passing a NULL pointer for either function.
    01221  *
    01222  * \param core A pointer to an AvrCore object.
    01223  *
    01224  * \param port_id The ID for handling the simulavr inheritance model.
    01225  *
    01226  * \param ext_rd Function for the device core to call when it needs to
    01227  * communicate with the external world via I/O Ports.
    01228  *
    01229  * \param ext_wr Function for the device core to call when it needs to
    01230  * communicate with the external world via I/O Ports.
    01231  *
    01232  */
    01233 void
    01234 avr_core_add_ext_rd_wr (AvrCore *core, int addr, PortFP_ExtRd ext_rd,
    01235                         PortFP_ExtWr ext_wr)
    01236 {
    01237     Port *p = (Port *)mem_get_vdevice_by_addr (core->mem, addr);
    01238
    01239     if (p == NULL)
    01240     {
    01241         avr_warning ("Device does not have vdevice at 0x%04x.\n", addr);
    01242         return;
    01243     }
    01244
    01245     port_add_ext_rd_wr (p, ext_rd, ext_wr);
    01246 }
    01247
    01248 /**
    01249  * \brief Add a new clock callback to list.
    01250  */
    01251 extern inline void avr_core_clk_cb_add (AvrCore *core, CallBack *cb);
    01252
    01253 /**
    01254  * \brief Add a new asynchronous callback to list.
    01255  */
    01256 extern inline void avr_core_async_cb_add (AvrCore *core, CallBack *cb);
    01257
    01258 /** \brief Run all the callbacks in the list.
    01259
    01260     If a callback returns non-zero (true), then it is done with it's job and
    01261     wishes to be removed from the list.
    01262
    01263     The time argument has dual meaning. If the callback list is for the clock
    01264     callbacks, time is the value of the CK clock counter. If the callback list
    01265     is for the asynchronous callback, time is the number of milliseconds from
    01266     some unknown, arbitrary time on the host system. */
    01267
    01268 extern inline void avr_core_clk_cb_exec (AvrCore *core);
    01269
    01270 /**
    01271  * \brief Run all the asynchronous callbacks.
    01272  */
    01273 extern inline void avr_core_async_cb_exec (AvrCore *core);
    01274
    01275 /*@}*/
    01276
    01277 /**
    01278  * \brief Dump the contents of the entire CPU core.
    01279  *
    01280  * \param core A pointer to an AvrCore object.
    01281  * \param f_core An open file descriptor.
    01282  */
    01283 void
    01284 avr_core_dump_core (AvrCore *core, FILE * f_core)
    01285 {
    01286     unsigned int pc = avr_core_PC_get (core);
    01287
    01288     fprintf (f_core, "PC = 0x%06x (PC*2 = 0x%06x)\n\n", pc, pc * 2);
    01289     mem_dump_core (core->mem, f_core);
    01290     flash_dump_core (core->flash, f_core);
    01291 }
    01292
    01293 /**
    01294  * \brief Load a program from an input file.
    01295  */
    01296 int
    01297 avr_core_load_program (AvrCore *core, char *file, int format)
    01298 {
    01299     return flash_load_from_file (core->flash, file, format);
    01300 }
    01301
    01302 /** \brief Load a program from an input file. */
    01303 int
    01304 avr_core_load_eeprom (AvrCore *core, char *file, int format)
    01305 {
    01306     EEProm *ee = (EEProm *)mem_get_vdevice_by_name (core->mem, "EEProm");
    01307
    01308     return eeprom_load_from_file (ee, file, format);
    01309 }

Automatically generated by Doxygen 1.5.5 on 7 Nov 2008.