Main Page

- Main Page
- Related Pages
- Files

- File List
- Globals

# stack.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: stack.c,v 1.15 2004/01/30 07:09:56 troth 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 /** \file stack.c
    00027     \brief Module for the definition of the stack.
    00028
    00029     Defines the classes stack, hw_stack, and mem_stack.
    00030
    00031     FIXME: Ted, I would really really really love to put in a description of
    00032     what is the difference between these three classes and how they're used,
    00033     but I don't understand it myself. */
    00034
    00035 #include <config.h>
    00036
    00037 #include <stdio.h>
    00038 #include <stdlib.h>
    00039 #include <string.h>
    00040
    00041 #include "avrerror.h"
    00042 #include "avrmalloc.h"
    00043 #include "avrclass.h"
    00044 #include "utils.h"
    00045 #include "callback.h"
    00046 #include "op_names.h"
    00047
    00048 #include "storage.h"
    00049 #include "flash.h"
    00050
    00051 #include "vdevs.h"
    00052 #include "memory.h"
    00053 #include "stack.h"
    00054 #include "register.h"
    00055 #include "sram.h"
    00056 #include "eeprom.h"
    00057 #include "timers.h"
    00058 #include "ports.h"
    00059
    00060 #include "avrcore.h"
    00061
    00062 #include "display.h"
    00063
    00064 static uint32_t hw_pop (Stack *stack, int bytes);
    00065 static void hw_push (Stack *stack, int bytes, uint32_t val);
    00066
    00067 static uint32_t mem_pop (Stack *stack, int bytes);
    00068 static void mem_push (Stack *stack, int bytes, uint32_t val);
    00069
    00070 /****************************************************************************\
    00071  *
    00072  * Stack(AvrClass) Definition.
    00073  *
    00074 \****************************************************************************/
    00075
    00076 /** \brief Allocates memory for a new Stack object
    00077
    00078     This is a virtual method for higher level stack implementations and as
    00079     such should not be used directly. */
    00080
    00081 Stack *
    00082 stack_new (StackFP_Pop pop, StackFP_Push push)
    00083 {
    00084     Stack *st;
    00085
    00086     st = avr_new (Stack, 1);
    00087     stack_construct (st, pop, push);
    00088     class_overload_destroy ((AvrClass *)st, stack_destroy);
    00089
    00090     return st;
    00091 }
    00092
    00093 /** \brief Constructor for the Stack class.
    00094
    00095     This is a virtual method for higher level stack implementations and as
    00096     such should not be used directly. */
    00097
    00098 void
    00099 stack_construct (Stack *stack, StackFP_Pop pop, StackFP_Push push)
    00100 {
    00101     if (stack == NULL)
    00102         avr_error ("passed null ptr");
    00103
    00104     class_construct ((AvrClass *)stack);
    00105
    00106     stack->pop = pop;
    00107     stack->push = push;
    00108 }
    00109
    00110 /** \brief Destructor for the Stack class.
    00111
    00112     This is a virtual method for higher level stack implementations and as
    00113     such should not be used directly. */
    00114
    00115 void
    00116 stack_destroy (void *stack)
    00117 {
    00118     if (stack == NULL)
    00119         return;
    00120
    00121     class_destroy (stack);
    00122 }
    00123
    00124 /** \brief Pops a byte or a word off the stack and returns it.
    00125     \param stack A pointer to the Stack object from which to pop
    00126     \param bytes Number of bytes to pop off the stack (1 to 4 bytes).
    00127
    00128     \return The 1 to 4 bytes value popped from the stack.
    00129
    00130     This method provides access to the derived class's pop() method. */
    00131
    00132 uint32_t
    00133 stack_pop (Stack *stack, int bytes)
    00134 {
    00135     return stack->pop (stack, bytes);
    00136 }
    00137
    00138 /** \brief Pushes a byte or a word of data onto the stack.
    00139     \param stack A pointer to the Stack object from which to pop.
    00140     \param bytes Size of the value being pushed onto the stack (1 to 4 bytes).
    00141     \param val The value to be pushed.
    00142
    00143     This method provides access to the derived class's push() method. */
    00144
    00145 void
    00146 stack_push (Stack *stack, int bytes, uint32_t val)
    00147 {
    00148     stack->push (stack, bytes, val);
    00149 }
    00150
    00151 /****************************************************************************\
    00152  *
    00153  * HWStack(Stack) Definition.
    00154  *
    00155 \****************************************************************************/
    00156
    00157 /** \brief Allocate a new HWStack object
    00158
    00159     This is the stack implementation used by devices which lack SRAM and only
    00160     have a fixed size hardware stack (e.i., the at90s1200) */
    00161
    00162 HWStack *
    00163 hwstack_new (int depth)
    00164 {
    00165     HWStack *st;
    00166
    00167     st = avr_new (HWStack, 1);
    00168     hwstack_construct (st, depth);
    00169     class_overload_destroy ((AvrClass *)st, hwstack_destroy);
    00170
    00171     return st;
    00172 }
    00173
    00174 /** \brief Constructor for HWStack object */
    00175
    00176 void
    00177 hwstack_construct (HWStack *stack, int depth)
    00178 {
    00179     if (stack == NULL)
    00180         avr_error ("passed null ptr");
    00181
    00182     stack_construct ((Stack *)stack, hw_pop, hw_push);
    00183
    00184     stack->depth = depth;
    00185     stack->stack = avr_new0 (uint32_t, depth);
    00186 }
    00187
    00188 /** \brief Destructor for HWStack object */
    00189
    00190 void
    00191 hwstack_destroy (void *stack)
    00192 {
    00193     if (stack == NULL)
    00194         return;
    00195
    00196     avr_free (((HWStack *)stack)->stack);
    00197     stack_destroy (stack);
    00198 }
    00199
    00200 /* The HWStack pop method. */
    00201
    00202 static uint32_t
    00203 hw_pop (Stack *stack, int bytes)
    00204 {
    00205     HWStack *hwst = (HWStack *)stack;
    00206     int i;
    00207     uint32_t val = hwst->stack[0];
    00208
    00209     for (i = 0; i < (hwst->depth - 1); i++)
    00210     {
    00211         hwst->stack[i] = hwst->stack[i + 1];
    00212     }
    00213
    00214     return val;
    00215 }
    00216
    00217 /* The HWStack push method. */
    00218
    00219 static void
    00220 hw_push (Stack *stack, int bytes, uint32_t val)
    00221 {
    00222     HWStack *hwst = (HWStack *)stack;
    00223     int i;
    00224
    00225     for (i = (hwst->depth - 1); i; i--)
    00226     {
    00227         hwst->stack[i - 1] = hwst->stack[i];
    00228     }
    00229
    00230     hwst->stack[0] = val;
    00231 }
    00232
    00233 /****************************************************************************\
    00234  *
    00235  * StackPointer(VDevice) Definition.
    00236  *
    00237 \****************************************************************************/
    00238
    00239 #ifndef DOXYGEN                 /* don't expose to doxygen */
    00240
    00241 typedef struct _StackPointer StackPointer;
    00242 struct _StackPointer
    00243 {
    00244     VDevice parent;
    00245
    00246     uint16_t SPL_addr;          /* Since some devices don't have a SPH, we
    00247                                    only track SPL address and assume the SPH
    00248                                    address is SPL_addr + 1. */
    00249
    00250     uint8_t SPL;                /* Low byte of stack pointer */
    00251     uint8_t SPH;                /* High byte of stack pointer */
    00252 };
    00253
    00254 #endif
    00255
    00256 static StackPointer *sp_new (int addr, char *name);
    00257 static void sp_construct (StackPointer *sp, int addr, char *name);
    00258 static void sp_destroy (void *sp);
    00259 static uint8_t sp_read (VDevice *dev, int addr);
    00260 static void sp_write (VDevice *dev, int addr, uint8_t val);
    00261 static void sp_reset (VDevice *dev);
    00262 static uint16_t sp_get (VDevice *sp);
    00263 static void sp_set (VDevice *sp, uint16_t val);
    00264 static void sp_add_addr (VDevice *vdev, int addr, char *name, int rel_addr,
    00265                          void *data);
    00266
    00267 /** \brief Create the Stack Pointer VDevice.
    00268
    00269     This should only be used in the DevSuppDefn io reg init structure. */
    00270
    00271 VDevice *
    00272 sp_create (int addr, char *name, int rel_addr, void *data)
    00273 {
    00274     return (VDevice *)sp_new (addr, name);
    00275 }
    00276
    00277 static StackPointer *
    00278 sp_new (int addr, char *name)
    00279 {
    00280     StackPointer *sp;
    00281
    00282     sp = avr_new (StackPointer, 1);
    00283     sp_construct (sp, addr, name);
    00284     class_overload_destroy ((AvrClass *)sp, sp_destroy);
    00285
    00286     return sp;
    00287 }
    00288
    00289 static void
    00290 sp_construct (StackPointer *sp, int addr, char *name)
    00291 {
    00292     if (sp == NULL)
    00293         avr_error ("passed null ptr");
    00294
    00295     vdev_construct ((VDevice *)sp, sp_read, sp_write, sp_reset, sp_add_addr);
    00296
    00297     sp_add_addr ((VDevice *)sp, addr, name, 0, NULL);
    00298
    00299     sp_reset ((VDevice *)sp);
    00300 }
    00301
    00302 static void
    00303 sp_destroy (void *sp)
    00304 {
    00305     if (sp == NULL)
    00306         return;
    00307
    00308     vdev_destroy (sp);
    00309 }
    00310
    00311 static uint8_t
    00312 sp_read (VDevice *dev, int addr)
    00313 {
    00314     StackPointer *sp = (StackPointer *)dev;
    00315
    00316     if (addr == sp->SPL_addr)
    00317         return sp->SPL;
    00318     else if (addr == (sp->SPL_addr + 1))
    00319         return sp->SPH;
    00320     else
    00321         avr_error ("Bad address: 0x%04x", addr);
    00322
    00323     return 0;
    00324 }
    00325
    00326 static void
    00327 sp_write (VDevice *dev, int addr, uint8_t val)
    00328 {
    00329     /* Don't need display_io_reg() here since it's called higher up in mem
    00330        chain. */
    00331
    00332     StackPointer *sp = (StackPointer *)dev;
    00333
    00334     if (addr == sp->SPL_addr)
    00335         sp->SPL = val;
    00336     else if (addr == (sp->SPL_addr + 1))
    00337         sp->SPH = val;
    00338     else
    00339         avr_error ("Bad address: 0x%04x", addr);
    00340 }
    00341
    00342 static void
    00343 sp_reset (VDevice *dev)
    00344 {
    00345     StackPointer *sp = (StackPointer *)dev;
    00346
    00347     display_io_reg (SPL_IO_REG, sp->SPL = 0);
    00348     display_io_reg (SPH_IO_REG, sp->SPH = 0);
    00349 }
    00350
    00351 static uint16_t
    00352 sp_get (VDevice *sp)
    00353 {
    00354     return (((StackPointer *)sp)->SPH << 8) + ((StackPointer *)sp)->SPL;
    00355 }
    00356
    00357 static void
    00358 sp_set (VDevice *sp, uint16_t val)
    00359 {
    00360     display_io_reg (SPL_IO_REG, ((StackPointer *)sp)->SPL = val & 0xff);
    00361     display_io_reg (SPH_IO_REG, ((StackPointer *)sp)->SPH = val >> 8);
    00362 }
    00363
    00364 static void
    00365 sp_add_addr (VDevice *vdev, int addr, char *name, int rel_addr, void *data)
    00366 {
    00367     StackPointer *sp = (StackPointer *)vdev;
    00368
    00369     if (strncmp ("SPL", name, 3) == 0)
    00370         sp->SPL_addr = addr;
    00371
    00372     else if (strncmp ("SPH", name, 3) == 0)
    00373         ;
    00374
    00375     else
    00376         avr_error ("Bad address: 0x%04x", addr);
    00377 }
    00378
    00379 /****************************************************************************\
    00380  *
    00381  * MemStack(Stack) Definition.
    00382  *
    00383 \****************************************************************************/
    00384
    00385 /** \brief Allocate a new MemStack object */
    00386
    00387 MemStack *
    00388 memstack_new (Memory *mem, int spl_addr)
    00389 {
    00390     MemStack *st;
    00391
    00392     st = avr_new (MemStack, 1);
    00393     memstack_construct (st, mem, spl_addr);
    00394     class_overload_destroy ((AvrClass *)st, memstack_destroy);
    00395
    00396     return st;
    00397 }
    00398
    00399 /** \brief Constructor for MemStack object */
    00400
    00401 void
    00402 memstack_construct (MemStack *stack, Memory *mem, int spl_addr)
    00403 {
    00404     if (stack == NULL)
    00405         avr_error ("passed null ptr");
    00406
    00407     stack_construct ((Stack *)stack, mem_pop, mem_push);
    00408
    00409     class_ref ((AvrClass *)mem);
    00410     stack->mem = mem;
    00411
    00412     stack->SP = mem_get_vdevice_by_addr (mem, spl_addr);
    00413     if (stack->SP == NULL)
    00414     {
    00415         avr_error ("attempt to attach non-extistant SPL register");
    00416     }
    00417     class_ref ((AvrClass *)stack->SP);
    00418 }
    00419
    00420 /** \brief Destructor for MemStack object */
    00421
    00422 void
    00423 memstack_destroy (void *stack)
    00424 {
    00425     MemStack *_stack = (MemStack *)stack;
    00426
    00427     if (stack == NULL)
    00428         return;
    00429
    00430     class_unref ((AvrClass *)_stack->SP);
    00431     class_unref ((AvrClass *)_stack->mem);
    00432
    00433     stack_destroy (stack);
    00434 }
    00435
    00436 /* The MemStack pop method */
    00437
    00438 static uint32_t
    00439 mem_pop (Stack *stack, int bytes)
    00440 {
    00441     MemStack *mst = (MemStack *)stack;
    00442     int i;
    00443     uint32_t val = 0;
    00444     uint16_t sp = sp_get (mst->SP);
    00445
    00446     if ((bytes < 0) || (bytes >= sizeof (uint32_t)))
    00447         avr_error ("bytes out of bounds: %d", bytes);
    00448
    00449     for (i = bytes - 1; i >= 0; i--)
    00450     {
    00451         sp++;
    00452         val |= (mem_read (mst->mem, sp) << (i * 8));
    00453     }
    00454
    00455     sp_set (mst->SP, sp);
    00456
    00457     return val;
    00458 }
    00459
    00460 /* The MemStack push method. */
    00461
    00462 static void
    00463 mem_push (Stack *stack, int bytes, uint32_t val)
    00464 {
    00465     MemStack *mst = (MemStack *)stack;
    00466     int i;
    00467     uint16_t sp = sp_get (mst->SP);
    00468
    00469     if ((bytes < 0) || (bytes >= sizeof (uint32_t)))
    00470         avr_error ("bytes out of bounds: %d", bytes);
    00471
    00472     for (i = 0; i < bytes; i++)
    00473     {
    00474         mem_write (mst->mem, sp, val & 0xff);
    00475         val >>= 8;
    00476         sp--;
    00477     }
    00478
    00479     sp_set (mst->SP, sp);
    00480 }

Automatically generated by Doxygen 1.7.2 on Wed Feb 22 2012.