avrcore.c

Go to the documentation of this file.
00001 /*
00002  * $Id: avrcore.c,v 1.88 2008/03/19 22:39:01 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 eeprom_sz = dev_supp_get_eeprom_sz (dev);
00382     int xram_sz = dev_supp_get_xram_sz (dev);
00383     int vtab_idx = dev_supp_get_vtab_idx (dev);
00384     int xram_end, sram_end;
00385     int addr;
00386 
00387     if (core == NULL)
00388         avr_error ("passed null ptr");
00389 
00390     class_construct ((AvrClass *)core);
00391 
00392     core->state = STATE_STOPPED;
00393     core->sleep_mode = 0;       /* each bit represents a sleep mode */
00394     core->PC = 0;
00395     core->PC_size = PC_sz;
00396     core->PC_max = flash_sz / 2; /* flash_sz is in bytes, need number of
00397                                     words here */
00398 
00399     core->flash = flash_new (flash_sz);
00400 
00401     core->breakpoints = NULL;
00402 
00403     core->irq_pending = NULL;
00404     core->irq_vtable = (IntVect *)(global_vtable_list[vtab_idx]);
00405     core->irq_offset = 0;
00406 
00407     core->CK = 0;
00408     core->inst_CKS = 0;
00409 
00410     core->clk_cb = NULL;
00411     core->async_cb = NULL;
00412 
00413     /* FIXME: hack to get it to compile. */
00414     if (dev_supp_has_ext_io_reg (dev))
00415         sram_end = 0xff + sram_sz;
00416     else
00417         sram_end = 0x5f + sram_sz;
00418     if (xram_sz)
00419         xram_end = 0xffff;
00420     else
00421         xram_end = sram_end;    /* i.e., no XRAM at all */
00422     if (dev_supp_has_ext_io_reg (dev))
00423         core->mem = mem_new (0x1f, 0xff, sram_end, xram_end);
00424     else
00425         core->mem = mem_new (0x1f, 0x5f, sram_end, xram_end);
00426 
00427     /* Attach the gpwr's to the memory bus. */
00428 
00429     core->gpwr = gpwr_new ();
00430     for (addr = 0; addr < 0x20; addr++)
00431     {
00432         static char *reg_name[] = { "r00", "r01", "r02", "r03", "r04", "r05",
00433                                     "r06", "r07", "r08", "r09", "r10", "r11",
00434                                     "r12", "r13", "r14", "r15", "r16", "r17",
00435                                     "r18", "r19", "r20", "r21", "r22", "r23",
00436                                     "r24", "r25", "r26", "r27", "r28", "r29",
00437                                     "r30", "r31" };
00438 
00439         avr_core_attach_vdev (core, addr, reg_name[addr],
00440                               (VDevice *)core->gpwr, 0, 0, 0xff, 0xff);
00441     }
00442 
00443     /* Setup EEPROM before IO regs since its object is re-used in the EEPROM
00444        control registers. */
00445     if (eeprom_sz)
00446     {
00447     core->eeprom = eeprom_new (eeprom_sz, mask_EERE | mask_EEWE | mask_EEMWE);
00448     }
00449     else
00450     {
00451     core->eeprom = NULL;
00452     }
00453 
00454     dev_supp_attach_io_regs (core, dev);
00455 
00456     /* Set up the stack. */
00457 
00458     if (stack_sz)
00459     {
00460         core->stack = (Stack *)hwstack_new (stack_sz);
00461     }
00462     else
00463     {
00464         /* Assuming that SPL is always at 0x5d. */
00465 
00466         core->stack = (Stack *)memstack_new (core->mem, 0x5d);
00467     }
00468 
00469     /* Assuming the SREG is always at 0x5f. */
00470 
00471     core->sreg = (SREG *)avr_core_get_vdev_by_addr (core, 0x5f);
00472     class_ref ((AvrClass *)core->sreg);
00473 
00474     /* Assuming that RAMPZ is always at 0x5b. If the device doesn't support
00475        RAMPZ, install a NULL pointer. */
00476 
00477     core->rampz = (RAMPZ *)avr_core_get_vdev_by_addr (core, 0x5b);
00478     if (core->rampz)
00479         class_ref ((AvrClass *)core->rampz);
00480 
00481     /* Attach the internal sram to the memory bus if needed. */
00482 
00483     if (sram_sz)
00484     {
00485         int base;
00486         VDevice *sram;
00487 
00488         if (dev_supp_has_ext_io_reg (dev))
00489             base = SRAM_EXTENDED_IO_BASE;
00490         else
00491             base = SRAM_BASE;
00492 
00493         core->sram = sram_new (base, sram_sz);
00494         sram = (VDevice *)core->sram;
00495 
00496         avr_message ("attach: Internal SRAM from 0x%04x to 0x%04x\n", base,
00497                      (base + sram_sz - 1));
00498 
00499         for (addr = base; addr < (base + sram_sz); addr++)
00500         {
00501             avr_core_attach_vdev (core, addr, "Internal SRAM", sram, 0, 0,
00502                                   0xff, 0xff);
00503         }
00504     }
00505     else
00506     {
00507         core->sram = NULL;
00508     }
00509 
00510     if (xram_sz)
00511     {
00512         int base;
00513         VDevice *xram;
00514 
00515         if (dev_supp_has_ext_io_reg (dev))
00516             base = SRAM_EXTENDED_IO_BASE + sram_sz;
00517         else
00518             base = SRAM_BASE + sram_sz;
00519 
00520         core->xram = sram_new (base, xram_sz);
00521         xram = (VDevice *)core->xram;
00522 
00523         avr_message ("attach: External SRAM from 0x%04x to 0x%04x\n", base,
00524                      (base + xram_sz - 1));
00525 
00526         for (addr = base; addr < (base + xram_sz); addr++)
00527         {
00528             avr_core_attach_vdev (core, addr, "External SRAM", xram, 0, 0,
00529                                   0xff, 0xff);
00530         }
00531     }
00532     else
00533     {
00534         core->xram = NULL;
00535     }
00536 
00537     /* Initialize the decoder lookup table */
00538 
00539     decode_init_lookup_table ();
00540 }
00541 
00542 /**
00543  * \brief Destructor for the AvrCore class.
00544  * 
00545  * Not to be called directly, except by a derived class.
00546  * Called via class_unref.
00547  */
00548 void
00549 avr_core_destroy (void *core)
00550 {
00551     AvrCore *_core = (AvrCore *)core;
00552 
00553     if (_core == NULL)
00554         return;
00555 
00556     class_unref ((AvrClass *)_core->sreg);
00557     class_unref ((AvrClass *)_core->flash);
00558     class_unref ((AvrClass *)_core->gpwr);
00559     class_unref ((AvrClass *)_core->mem);
00560     class_unref ((AvrClass *)_core->stack);
00561 
00562     dlist_delete_all (_core->breakpoints);
00563     dlist_delete_all (_core->clk_cb);
00564     dlist_delete_all (_core->async_cb);
00565     dlist_delete_all (_core->irq_pending);
00566 
00567     class_destroy (core);
00568 }
00569 
00570 /** \brief Query the sizes of the 3 memory spaces: flash, sram, and eeprom. */
00571 void
00572 avr_core_get_sizes (AvrCore *core, int *flash, int *sram, int *sram_start,
00573                     int *eeprom)
00574 {
00575     *flash = flash_get_size (core->flash);
00576 
00577     if (core->sram)
00578     {
00579         *sram = sram_get_size (core->sram);
00580         *sram_start = sram_get_base (core->sram);
00581     }
00582     else
00583     {
00584         *sram = 0;
00585         *sram_start = 0;
00586     }
00587 
00588     if (core->eeprom)
00589         *eeprom = eeprom_get_size (core->eeprom);
00590     else
00591         *eeprom = 0;
00592 }
00593 
00594 /** \brief Attach a virtual device into the Memory. */
00595 extern inline void avr_core_attach_vdev (AvrCore *core, uint16_t addr,
00596                                          char *name, VDevice *vdev,
00597                                          int flags, uint8_t reset_value,
00598                                          uint8_t rd_mask, uint8_t wr_mask);
00599 
00600 /** \brief Returns the \c VDevice with the name \a name. */
00601 extern inline VDevice *avr_core_get_vdev_by_name (AvrCore *core, char *name);
00602 
00603 /** \brief Returns the \c VDevice which handles the address \a addr. */
00604 extern inline VDevice *avr_core_get_vdev_by_addr (AvrCore *core, int addr);
00605 
00606 /** \brief Sets the device's state (running, stopped, breakpoint, sleep). */
00607 extern inline void avr_core_set_state (AvrCore *core, StateType state);
00608 
00609 /** \brief Returns the device's state (running, stopped, breakpoint, sleep). */
00610 extern inline int avr_core_get_state (AvrCore *core);
00611 
00612 /** \brief Sets the device to a sleep state.
00613   * \param core Pointer to the core.
00614   * \param sleep_mode The BITNUMBER of the sleepstate.
00615   */
00616 extern inline void avr_core_set_sleep_mode (AvrCore *core, int sleep_mode);
00617 
00618 /** \brief Return the device's sleepmode. */
00619 extern inline int avr_core_get_sleep_mode (AvrCore *core);
00620 
00621 /*@}*/
00622 
00623 /** \name Program Memory Space Access Methods */
00624 
00625 /*@{*/
00626 
00627 /** \brief Reads a word from flash memory. */
00628 static uint16_t avr_core_flash_read (AvrCore *core, int addr);
00629 
00630 /** \brief Writes a word to flash memory. */
00631 static void avr_core_flash_write (AvrCore *core, int addr,
00632                                          uint16_t val);
00633 
00634 /** \brief Writes a byte to flash memory.
00635   *
00636   * This function writes the lower 8 bit of a flash word.
00637   * Use avr_core_flash_write() write to write a full word,
00638   * or avr_core_flash_write_hi8() to write the upper 8 bits.
00639   */
00640 static void avr_core_flash_write_lo8 (AvrCore *core, int addr,
00641                                              uint8_t val);
00642 
00643 /** \brief Writes a byte to flash memory.
00644   *
00645   * This function writes the upper 8 bit of a flash word.
00646   * Use avr_core_flash_write() write to write a full word,
00647   * or avr_core_flash_write_lo8() to write the lower 8 bits.
00648   */
00649 static void avr_core_flash_write_hi8 (AvrCore *core, int addr,
00650                                              uint8_t val);
00651 
00652 /*@}*/
00653 
00654 /** \name Data Memory Space Access Methods */
00655 
00656 /*@{*/
00657 
00658 /** \brief Reads a byte from memory.
00659   *
00660   * This accesses the \a register \a file and the \a SRAM.
00661   */
00662 static uint8_t avr_core_mem_read (AvrCore *core, int addr);
00663 
00664 /** \brief Writes a byte to memory.
00665   *
00666   * This accesses the \a register \a file and the \a SRAM.
00667   */
00668 static void avr_core_mem_write (AvrCore *core, int addr, uint8_t val);
00669 
00670 /*@}*/
00671 
00672 /** \name Status Register Access Methods */
00673 
00674 /*@{*/
00675 
00676 /** \brief Get the value of the status register. */
00677 
00678 static uint8_t avr_core_sreg_get (AvrCore *core);
00679 
00680 /** \brief Set the value of the status register. */
00681 
00682 static void avr_core_sreg_set (AvrCore *core, uint8_t v);
00683 
00684 /** \brief Get the value of bit \c b of the status register. */
00685 
00686 extern inline int avr_core_sreg_get_bit (AvrCore *core, int b);
00687 
00688 /** \brief Set the value of bit \c b of the status register. */
00689 
00690 extern inline void avr_core_sreg_set_bit (AvrCore *core, int b, int v);
00691 
00692 /*@}*/
00693 
00694 /** \name RAMPZ access methods */
00695 
00696 /*@{*/
00697 
00698 /** \brief Get the value of the rampz register. */
00699 
00700 extern inline uint8_t avr_core_rampz_get (AvrCore *core);
00701 
00702 /** \brief Set the value of the rampz register. */
00703 
00704 extern inline void avr_core_rampz_set (AvrCore *core, uint8_t v);
00705 
00706 /*@}*/
00707 
00708 /**
00709  * \Name General Purpose Working Register Access Methods
00710  */
00711 
00712 /*@{*/
00713 
00714 /** \brief Returns a GPWR's(\a r0-r31) value. */
00715 static uint8_t avr_core_gpwr_get (AvrCore *core, int reg);
00716 
00717 /** \brief Writes a GPWR's (\a r0-r31) value. */
00718 static void avr_core_gpwr_set (AvrCore *core, int reg, uint8_t val);
00719 
00720 /*@}*/
00721 
00722 /**
00723  * \name Direct I/O Register Access Methods
00724  *
00725  * IO Registers are mapped in memory directly after the 32 (0x20)
00726  * general registers.
00727  */
00728 
00729 /*@{*/
00730 
00731 /** \brief Displays all registers. */
00732 void
00733 avr_core_io_display_names (AvrCore *core)
00734 {
00735     int i;
00736     uint8_t val;
00737     char name[80];
00738 
00739     for (i = IO_REG_ADDR_BEGIN; i < IO_REG_ADDR_END; i++)
00740     {
00741         mem_io_fetch (core->mem, i, &val, name, sizeof (name) - 1);
00742         display_io_reg_name (i - IO_REG_ADDR_BEGIN, name);
00743     }
00744 }
00745 
00746 /** \brief Reads the value of a register.
00747   * \param core Pointer to the core.
00748   * \param reg The registers address. This address is counted above the
00749   *  beginning of the registers memory block (0x20).
00750   */
00751 extern inline uint8_t avr_core_io_read (AvrCore *core, int reg);
00752 
00753 /** \brief Writes the value of a register.
00754   * See avr_core_io_read() for a discussion of \a reg. */
00755 extern inline void avr_core_io_write (AvrCore *core, int reg, uint8_t val);
00756 
00757 /** \brief Read an io register into val and put the name of the register into
00758   * buf. */
00759 static void avr_core_io_fetch (AvrCore *core, int reg, uint8_t * val,
00760                                       char *buf, int bufsiz);
00761 
00762 /*@}*/
00763 
00764 /** \name Stack Methods */
00765 
00766 /*@{*/
00767 
00768 /** \brief Pop 1-4 bytes off of the stack.
00769  *
00770  * See stack_pop() for more details.
00771  */
00772 extern inline uint32_t avr_core_stack_pop (AvrCore *core, int bytes);
00773 
00774 /** \brief Push 1-4 bytes onto the stack.
00775  *
00776  * See stack_push() for more details.
00777  */
00778 extern inline void avr_core_stack_push (AvrCore *core, int bytes,
00779                                         uint32_t val);
00780 
00781 /*@}*/
00782 
00783 /** \name Program Counter Methods */
00784 
00785 /*@{*/
00786 
00787 /** \brief Returns the size of the Program Counter in bytes.
00788  *
00789  * Most devices have a 16-bit PC (2 bytes), but some larger ones
00790  * (e.g. mega256), have a 22-bit PC (3 bytes).
00791  */
00792 extern inline int32_t avr_core_PC_size (AvrCore *core);
00793 
00794 /** \brief Returns the maximum value of the Program Counter.
00795  *
00796  * This is flash_size / 2.
00797  */
00798 static int32_t avr_core_PC_max (AvrCore *core);
00799 
00800 /** \brief Return the current of the Program Counter. */
00801 static int32_t avr_core_PC_get (AvrCore *core);
00802 
00803 /** \brief Set the Program Counter to val.
00804  *
00805  * If val is not in the valid range of PC values, it is adjusted to fall in
00806  * the valid range.
00807  */
00808 static void avr_core_PC_set (AvrCore *core, int32_t val);
00809 
00810 /** \brief Increment the Program Counter by val.
00811  *
00812  * val can be either positive or negative.
00813  *
00814  * If the result of the incrememt is outside the valid range for PC, it is
00815  * adjusted to fall in the valid range. This allows addresses to wrap around
00816  * the end of the insn space.
00817  */
00818 extern inline void avr_core_PC_incr (AvrCore *core, int val);
00819 
00820 /*@}*/
00821 
00822 /** \name Methods for accessing CK and instruction Clocks */
00823 
00824 /*@{*/
00825 
00826 /** \brief Get the current clock counter. */
00827 extern inline uint64_t avr_core_CK_get (AvrCore *core);
00828 
00829 /** \brief Increment the clock counter. */
00830 extern inline void avr_core_CK_incr (AvrCore *core);
00831 
00832 /** \brief Get the number of clock cycles remaining for the currently
00833  *  executing instruction. */
00834 extern inline int avr_core_inst_CKS_get (AvrCore *core);
00835 
00836 /** \brief Set the number of clock cycles for the instruction being
00837  *  executed. */
00838 extern inline void avr_core_inst_CKS_set (AvrCore *core, int val);
00839 
00840 /** \name Interrupt Access Methods. */
00841 
00842 /*@{*/
00843 
00844 /** \brief Gets the first pending irq. */
00845 IntVect *
00846 avr_core_irq_get_pending (AvrCore *core)
00847 {
00848     return irq_get_pending_vector (core->irq_pending, core->state,
00849                                    core->sleep_mode);
00850 }
00851 
00852 /** \brief Raises an irq by adding it's data to the irq_pending list. */
00853 void
00854 avr_core_irq_raise (AvrCore *core, unsigned int irq)
00855 {
00856     IntVect *irq_ptr = &core->irq_vtable[irq];
00857 
00858 #if !defined(DISABLE_IRQ_MESSAGES)
00859     avr_message ("Raising irq # %u [%s at 0x%x]\n", irq, irq_ptr->name,
00860                  irq_ptr->addr * 2);
00861 #endif
00862     core->irq_pending = irq_list_add (core->irq_pending, irq_ptr);
00863 }
00864 
00865 /** \brief Calls the interrupt's callback to clear the flag. */
00866 void
00867 avr_core_irq_clear (AvrCore *core, IntVect *irq)
00868 {
00869     core->irq_pending = irq_list_delete (core->irq_pending, irq);
00870 }
00871 
00872 /** \brief Removes all irqs from the irq_pending list. */
00873 extern inline void avr_core_irq_clear_all (AvrCore *core);
00874 
00875 /*@}*/
00876 
00877 /** \name Break point access methods. */
00878 
00879 /*@{*/
00880 
00881 /** \brief Inserts a break point. */
00882 
00883 void
00884 avr_core_insert_breakpoint (AvrCore *core, int pc)
00885 {
00886 #define BREAK_OPCODE 0x9598
00887 
00888     uint16_t insn = flash_read (core->flash, pc);
00889 
00890     core->breakpoints = brk_pt_list_add (core->breakpoints, pc, insn);
00891 
00892     flash_write (core->flash, pc, BREAK_OPCODE);
00893 }
00894 
00895 /** \brief Removes a break point. */
00896 
00897 void
00898 avr_core_remove_breakpoint (AvrCore *core, int pc)
00899 {
00900     BreakPt *bp;
00901 
00902     bp = brk_pt_list_lookup (core->breakpoints, pc);
00903     if (bp)
00904     {
00905         uint16_t insn = bp->opcode;
00906 
00907         core->breakpoints = brk_pt_list_delete (core->breakpoints, pc);
00908 
00909         flash_write (core->flash, pc, insn);
00910     }
00911 }
00912 
00913 #ifndef DOXYGEN                 /* don't expose to doxygen */
00914 
00915 struct bp_enable_data
00916 {
00917     AvrCore *core;
00918     int enable;
00919 };
00920 
00921 #endif /* DOXYGEN */
00922 
00923 static int
00924 iter_enable_breakpoint (AvrClass *data, void *user_data)
00925 {
00926     BreakPt *bp = (BreakPt *)data;
00927     struct bp_enable_data *bed = (struct bp_enable_data *)user_data;
00928 
00929     if (bed->enable)
00930     {
00931         uint16_t insn = flash_read (bed->core->flash, bp->pc);
00932 
00933         if (insn != BREAK_OPCODE)
00934         {
00935             /* Enable the breakpoint */
00936             bp->opcode = insn;
00937             flash_write (bed->core->flash, bp->pc, BREAK_OPCODE);
00938         }
00939     }
00940     else
00941     {
00942         /* Disable the breakpoint */
00943         flash_write (bed->core->flash, bp->pc, bp->opcode);
00944     }
00945 
00946     return 0;                   /* Don't delete any item from the list. */
00947 }
00948 
00949 /** \brief Disable breakpoints.
00950 
00951     Disables all breakpoints that where set using avr_core_insert_breakpoint().
00952     The breakpoints are not removed from the breakpoint list.  */
00953 
00954 void
00955 avr_core_disable_breakpoints (AvrCore *core)
00956 {
00957     struct bp_enable_data bed = { core, 0 };
00958 
00959     core->breakpoints =
00960         brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed);
00961 }
00962 
00963 /** \brief Enable breakpoints. 
00964 
00965     Enables all breakpoints that where previous disabled. */
00966 
00967 void
00968 avr_core_enable_breakpoints (AvrCore *core)
00969 {
00970     struct bp_enable_data bed = { core, 1 };
00971 
00972     core->breakpoints =
00973         brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed);
00974 }
00975 
00976 /*@}*/
00977 
00978 /* Private
00979   
00980    Execute an instruction.
00981    Presets the number of instruction clocks to zero so that break points and
00982    invalid opcodes don't add extraneous clock counts.
00983    
00984    Also checks for software breakpoints. 
00985    Any opcode except 0xffff can be a breakpoint.
00986    
00987    Returns BREAK_POINT, or >= 0. */
00988 
00989 static int
00990 exec_next_instruction (AvrCore *core)
00991 {
00992     int result, pc;
00993     uint16_t opcode;
00994     struct opcode_info *opi;
00995 
00996     pc = avr_core_PC_get (core);
00997     opcode = flash_read (core->flash, pc);
00998 
00999     /* Preset the number of instruction clocks to zero so that break points
01000        and invalid opcodes don't add extraneous clock counts. */
01001     avr_core_inst_CKS_set (core, 0);
01002 
01003     opi = decode_opcode (opcode);
01004 
01005     result = opi->func (core, opcode, opi->arg1, opi->arg2);
01006 
01007     if (global_debug_inst_output)
01008         fprintf (stderr, "0x%06x (0x%06x) : 0x%04x : %s\n", pc, pc * 2,
01009                  opcode, global_opcode_name[result]);
01010 
01011     return result;
01012 }
01013 
01014 /** \name Program control methods */
01015 
01016 /*@{*/
01017 
01018 /*
01019  * Private
01020  *
01021  * Checks to see if an interrupt is pending. If any are pending, and
01022  * if SREG(I) is set, the following will occur:
01023  *   - push current PC onto stack
01024  *   - PC <- interrupt vector
01025  *   - I flag of SREG is cleared
01026  *
01027  * Reset vector is not controlled by the SREG(I) flag, thus if reset
01028  * interrupt has occurred, the device will be reset irregardless of state
01029  * of SREG(I).
01030  *
01031  * \note There are different ways of doing this:
01032  * - In register.c  wdtcr_intr_cb() we can directly reset the MCU without
01033  *   the use of irqs. This would require to make the callback an async
01034  *   callback and it would allow the speed improvments commented out below
01035  *   to be activated.
01036  * - Keep it as an interrupt an waste CPU time.
01037  *
01038  * Ted, what do you think we should do?
01039  */
01040 
01041 static void
01042 avr_core_check_interrupts (AvrCore *core)
01043 {
01044     IntVect *irq;
01045 
01046     if (core->irq_pending)
01047     {
01048         irq = avr_core_irq_get_pending (core);
01049 
01050         if (irq)
01051         {
01052             if (irq->name == NULL)
01053             {
01054                 avr_error ("Raised an invalid irq for device");
01055             }
01056 
01057             if (irq->addr == IRQ_RESET_ADDR)
01058             {
01059                 /* The global interrupt (SREG.I) never blocks a reset. We
01060                    don't need to clear the irq since a reset clears all
01061                    pending irq's. */
01062                 avr_core_reset (core);
01063             }
01064 
01065             if (avr_core_sreg_get_bit (core, SREG_I))
01066             {
01067                 int pc = avr_core_PC_get (core);
01068                 int pc_bytes = avr_core_PC_size (core);
01069 
01070                 avr_core_stack_push (core, pc_bytes, pc);
01071                 avr_core_sreg_set_bit (core, SREG_I, 0);
01072 
01073 #if !defined(DISABLE_IRQ_MESSAGES)
01074                 avr_message ("Vectoring to irq at addr:0x%x offset:0x%x\n",
01075                              irq->addr * 2, core->irq_offset * 2);
01076 #endif
01077 
01078                 avr_core_PC_set (core, irq->addr + core->irq_offset);
01079 
01080                 avr_core_irq_clear (core, irq);
01081             }
01082         }
01083     }
01084 }
01085 
01086 /**
01087  * \brief Process a single program instruction, all side effects and
01088  * peripheral stimulii.
01089  *
01090  * Executes instructions, calls callbacks, and checks for interrupts.  */
01091 
01092 int
01093 avr_core_step (AvrCore *core)
01094 {
01095     int res = 0;
01096     int state;
01097 
01098     /* The MCU is stopped when in one of the many sleep modes */
01099     state = avr_core_get_state (core);
01100     if (state != STATE_SLEEP)
01101     {
01102         /* execute an instruction; may change state */
01103         res = exec_next_instruction (core);
01104     }
01105 
01106     /* Execute the clock callbacks */
01107     while (core->inst_CKS > 0)
01108     {
01109         /* propagate clocks here */
01110         avr_core_clk_cb_exec (core);
01111 
01112         avr_core_CK_incr (core);
01113 
01114         core->inst_CKS--;
01115     }
01116 
01117     /* FIXME: async cb's and interrupt checking might need to be put 
01118        somewhere else. */
01119 
01120     /* Execute the asynchronous callbacks */
01121     avr_core_async_cb_exec (core);
01122 
01123     /* Check interrupts here. If the previous instruction was a reti, then we
01124        need to delay handling of any pending IRQs until after the next
01125        instruction is executed. */
01126     if (res != opcode_RETI)
01127         avr_core_check_interrupts (core);
01128 
01129     return res;
01130 }
01131 
01132 /** \brief Start the processing of instructions by the simulator.
01133  *
01134  * The simulated device will run until one of the following occurs:
01135  *   - The state of the core is no longer STATE_RUNNING.
01136  *   - The simulator receives a SIGINT signal.
01137  *   - A breakpoint is reached (currently causes core to stop running).
01138  *   - A fatal internal error occurs.
01139  *
01140  * \note When running simulavr in gdb server mode, this function is not
01141  * used. The avr_core_step() function is called repeatedly in a loop when the
01142  * continue command is issued from gdb. As such, the functionality in this
01143  * loop should be kept to a minimum.
01144  *
01145  * \todo Should add some basic breakpoint handling here. Maybe allow
01146  * continuing, and simple breakpoint management (disable, delete, set)
01147  */
01148 
01149 void
01150 avr_core_run (AvrCore *core)
01151 {
01152     uint64_t cnt = 0;
01153     int res;
01154     uint64_t start_time, run_time;
01155 
01156     avr_core_reset (core);      /* make sure the device is in a sane state. */
01157 
01158     core->state = STATE_RUNNING;
01159 
01160     signal_watch_start (SIGINT);
01161 
01162     /* FIXME: [TRoth 2002/03/19] This loop isn't going to handle sleep or idle
01163        modes properly. */
01164 
01165     start_time = get_program_time ();
01166     while (core->state == STATE_RUNNING)
01167     {
01168         if (signal_has_occurred (SIGINT))
01169             break;
01170 
01171         res = avr_core_step (core);
01172 
01173         if (res == BREAK_POINT)
01174             break;
01175 
01176         cnt++;
01177     }
01178     run_time = get_program_time () - start_time;
01179 
01180     signal_watch_stop (SIGINT);
01181     
01182     /* avoid division by zero below */
01183     if (run_time == 0) run_time = 1;
01184     
01185     avr_message ("Run time was %lld.%03lld seconds.\n", run_time / 1000,
01186                  run_time % 1000);
01187 
01188     if (run_time == 0)
01189          run_time = 1;          /* Avoid division by zero. */
01190 
01191     avr_message ("Executed %lld instructions.\n", cnt);
01192     avr_message ("   %lld insns/sec\n", (cnt * 1000) / run_time);
01193     avr_message ("Executed %lld clock cycles.\n", avr_core_CK_get (core));
01194     avr_message ("   %lld clks/sec\n",
01195                  (avr_core_CK_get (core) * 1000) / run_time);
01196 }
01197 
01198 /** \brief Sets the simulated CPU back to its initial state.
01199  *
01200  *  Zeroes out PC, IRQ's, clock, and memory.
01201  */
01202 
01203 void
01204 avr_core_reset (AvrCore *core)
01205 {
01206     avr_core_PC_set (core, 0);
01207     avr_core_irq_clear_all (core);
01208 
01209     avr_core_inst_CKS_set (core, 0);
01210 
01211     /* Send clock cycles to display.
01212        Normaly the clockcycles must not be reset here!
01213        This leads to an error in the vcd file. */
01214 
01215     display_clock (core->CK);
01216 
01217     mem_reset (core->mem);
01218 }
01219 
01220 /*@}*/
01221 
01222 /** \name Callback Handling Methods */
01223 
01224 /*@{*/
01225 
01226 /**
01227  * \brief For adding external read and write callback functions.
01228  *
01229  * rd and wr should come in pairs, but it is safe to add
01230  * empty function via passing a NULL pointer for either function.
01231  *
01232  * \param core A pointer to an AvrCore object.
01233  *
01234  * \param port_id The ID for handling the simulavr inheritance model.
01235  *
01236  * \param ext_rd Function for the device core to call when it needs to
01237  * communicate with the external world via I/O Ports.
01238  *
01239  * \param ext_wr Function for the device core to call when it needs to
01240  * communicate with the external world via I/O Ports.
01241  *
01242  */
01243 void
01244 avr_core_add_ext_rd_wr (AvrCore *core, int addr, PortFP_ExtRd ext_rd,
01245                         PortFP_ExtWr ext_wr)
01246 {
01247     Port *p = (Port *)mem_get_vdevice_by_addr (core->mem, addr);
01248 
01249     if (p == NULL)
01250     {
01251         avr_warning ("Device does not have vdevice at 0x%04x.\n", addr);
01252         return;
01253     }
01254 
01255     port_add_ext_rd_wr (p, ext_rd, ext_wr);
01256 }
01257 
01258 /**
01259  * \brief Add a new clock callback to list.
01260  */
01261 extern inline void avr_core_clk_cb_add (AvrCore *core, CallBack *cb);
01262 
01263 /**
01264  * \brief Add a new asynchronous callback to list.
01265  */
01266 extern inline void avr_core_async_cb_add (AvrCore *core, CallBack *cb);
01267 
01268 /** \brief Run all the callbacks in the list.
01269  
01270     If a callback returns non-zero (true), then it is done with it's job and
01271     wishes to be removed from the list.
01272  
01273     The time argument has dual meaning. If the callback list is for the clock
01274     callbacks, time is the value of the CK clock counter. If the callback list
01275     is for the asynchronous callback, time is the number of milliseconds from
01276     some unknown, arbitrary time on the host system. */
01277 
01278 extern inline void avr_core_clk_cb_exec (AvrCore *core);
01279 
01280 /**
01281  * \brief Run all the asynchronous callbacks.
01282  */
01283 extern inline void avr_core_async_cb_exec (AvrCore *core);
01284 
01285 /*@}*/
01286 
01287 /**
01288  * \brief Dump the contents of the entire CPU core.
01289  *
01290  * \param core A pointer to an AvrCore object.
01291  * \param f_core An open file descriptor.
01292  */
01293 void
01294 avr_core_dump_core (AvrCore *core, FILE * f_core)
01295 {
01296     unsigned int pc = avr_core_PC_get (core);
01297 
01298     fprintf (f_core, "PC = 0x%06x (PC*2 = 0x%06x)\n\n", pc, pc * 2);
01299     mem_dump_core (core->mem, f_core);
01300     flash_dump_core (core->flash, f_core);
01301 }
01302 
01303 /**
01304  * \brief Load a program from an input file.
01305  */
01306 int
01307 avr_core_load_program (AvrCore *core, char *file, int format)
01308 {
01309     return flash_load_from_file (core->flash, file, format);
01310 }
01311 
01312 /** \brief Load a program from an input file. */
01313 int
01314 avr_core_load_eeprom (AvrCore *core, char *file, int format)
01315 {
01316     EEProm *ee = (EEProm *)mem_get_vdevice_by_name (core->mem, "EEProm");
01317 
01318     return eeprom_load_from_file (ee, file, format);
01319 }