00001 /* 00002 * OpenBIOS - free your system! 00003 * ( FCode tokenizer ) 00004 * 00005 * stack.c - data and return stack handling for fcode tokenizer. 00006 * 00007 * This program is part of a free implementation of the IEEE 1275-1994 00008 * Standard for Boot (Initialization Configuration) Firmware. 00009 * 00010 * Copyright (C) 2001-2005 by Stefan Reinauer <stepan@openbios.org> 00011 * 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU General Public License as published by 00014 * the Free Software Foundation; version 2 of the License. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA 00024 * 00025 */ 00026 00027 /* ************************************************************************** 00028 * Modifications made in 2005 by IBM Corporation 00029 * (C) Copyright 2005 IBM Corporation. All Rights Reserved. 00030 * Modifications Author: David L. Paktor dlpaktor@us.ibm.com 00031 **************************************************************************** */ 00032 00033 #include <stdlib.h> 00034 #include <stdio.h> 00035 #include <string.h> 00036 00037 #include "stack.h" 00038 #include "scanner.h" 00039 #include "errhandler.h" 00040 00041 /* ************************************************************************** 00042 * 00043 * Global Variables Imported 00044 * statbuf The word just read from the input stream 00045 * 00046 **************************************************************************** */ 00047 00048 00049 /* ************************************************************************** 00050 * 00051 * Global Variables Exported 00052 * dstack Pointer to current item on top of Data Stack 00053 * 00054 **************************************************************************** */ 00055 00056 long *dstack; 00057 00058 /* ************************************************************************** 00059 * 00060 * Local/Static Pointers ..... to ... -> Points to ... 00061 * startdstack Start of data-stack area -> last possible item 00062 * enddstack End of data-stack area -> past first item 00063 * 00064 *************************************************************************** */ 00065 00066 static long *startdstack; 00067 static long *enddstack; 00068 00069 void clear_stack(void) 00070 { 00071 dstack = enddstack; 00072 } 00073 00074 /* internal stack functions */ 00075 00076 void init_stack(void) 00077 { 00078 startdstack = safe_malloc(MAX_ELEMENTS*sizeof(long), "initting stack"); 00079 enddstack = startdstack + MAX_ELEMENTS; 00080 dstack=enddstack; 00081 } 00082 00083 /* Input Param: stat TRUE = Underflow, FALSE = Overflow */ 00084 static void stackerror(bool stat) 00085 { 00086 /* 00087 * Because all of our stack operations are protected and 00088 * we have no risk of the dstack pointer going into 00089 * invalid territory, this error needs not be FATAL. 00090 */ 00091 tokenization_error ( TKERROR , "stack %sflow at or near %s \n", 00092 (stat)?"under":"over" , statbuf ); 00093 } 00094 00095 /* 00096 * Return TRUE if the stack depth is equal to or greater than 00097 * the supplied minimum requirement. If not, print an error. 00098 */ 00099 bool min_stack_depth(int mindep) 00100 { 00101 bool retval = TRUE ; 00102 long *stack_result; 00103 00104 stack_result = dstack + mindep; 00105 /* 00106 * The above appears counter-intuitive. However, C compensates 00107 * for the size of the object of a pointer when it handles 00108 * address arithmetic. A more explicit expression that would 00109 * yield the same result, might look something like this: 00110 * 00111 * (long *)((int)dstack + (mindep * sizeof(long))) 00112 * 00113 * I doubt that that form would yield tighter code, or otherwise 00114 * represent any material advantage... 00115 */ 00116 00117 if ( stack_result > enddstack ) 00118 { 00119 retval = FALSE; 00120 stackerror(TRUE); 00121 } 00122 00123 return ( retval ); 00124 } 00125 00126 /* 00127 * Return TRUE if the stack has room for the supplied # of items 00128 */ 00129 static bool room_on_stack_for(int newdep) 00130 { 00131 bool retval = TRUE ; 00132 long *stack_result; 00133 00134 stack_result = dstack - newdep; 00135 /* See above note about "counter-intuitive" pointer address arithmetic */ 00136 00137 if ( stack_result < startdstack ) 00138 { 00139 retval = FALSE; 00140 stackerror(FALSE); 00141 } 00142 00143 return ( retval ); 00144 } 00145 00146 void dpush(long data) 00147 { 00148 #ifdef DEBUG_DSTACK 00149 printf("dpush: sp=%p, data=0x%lx, ", dstack, data); 00150 #endif 00151 if ( room_on_stack_for(1) ) 00152 { 00153 --dstack; 00154 *(dstack)=data; 00155 } 00156 } 00157 00158 long dpop(void) 00159 { 00160 long val = 0; 00161 #ifdef DEBUG_DSTACK 00162 printf("dpop: sp=%p, data=0x%lx, ",dstack, *dstack); 00163 #endif 00164 if ( min_stack_depth(1) ) 00165 { 00166 val=*(dstack); 00167 dstack++; 00168 } 00169 return val; 00170 } 00171 00172 long dget(void) 00173 { 00174 long val = 0; 00175 if ( min_stack_depth(1) ) 00176 { 00177 val = *(dstack); 00178 } 00179 return val; 00180 } 00181 00182 long stackdepth(void) 00183 { 00184 long depth; 00185 00186 depth = enddstack - dstack; 00187 /* 00188 * Again, C's address arithmetic compensation comes into play. 00189 * See the note at min_stack_depth() 00190 * 00191 * A more explicit equivalent expression might look like this: 00192 * 00193 * (((long int)enddstack - (long int)dstack) / sizeof(long)) 00194 * 00195 * I doubt any material advantage with that one either... 00196 */ 00197 00198 return (depth); 00199 } 00200 00201 void swap(void) 00202 { 00203 long nos_temp; /* Next-On-Stack temp */ 00204 if ( min_stack_depth(2) ) 00205 { 00206 nos_temp = dstack[1]; 00207 dstack[1]= dstack[0]; 00208 dstack[0]= nos_temp; 00209 } 00210 } 00211 00212 void two_swap(void) 00213 { 00214 long two_deep, three_deep; 00215 if ( min_stack_depth(4) ) 00216 { 00217 two_deep = dstack[2]; 00218 three_deep = dstack[3]; 00219 dstack[2] = dstack[0]; 00220 dstack[3] = dstack[1]; 00221 dstack[1] = three_deep; 00222 dstack[0] = two_deep; 00223 } 00224 } 00225 00226