diff -Naur ORIG/brickos-0.2.6.10/configure BRICK-CYCLONE/brickos-0.2.6.10/configure --- ORIG/brickos-0.2.6.10/configure 2002-11-07 12:00:11.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/configure 2003-11-13 13:24:01.000000000 -0700 @@ -92,6 +92,7 @@ BASENAME=`basename $HMSFULL` TOOLPREFIX=$DIRNAME/$(echo $BASENAME | sed "s/gcc.*//") +H8_ARCH=$(echo $BASENAME | sed "s/-gcc.*//") echo " - Toolprefix = "$TOOLPREFIX @@ -132,6 +133,7 @@ -v cc=$CC \ -v cflags="$CFLAGS" \ -v toolPrefix="$TOOLPREFIX" \ + -v h8_arch="$H8_ARCH" \ -v mkdep="$MAKEDEPEND" \ -v brickosRoot=$BRICKOS_ROOT \ -v cflgPleq=$CFLG_PE \ @@ -144,6 +146,7 @@ inInsert=0 print sep print "TOOLPREFIX=" toolPrefix + print "H8_ARCH=" h8_arch print "SED_SFLAG=" sedFlag print "EXT=" ext print "CC=" cc diff -Naur ORIG/brickos-0.2.6.10/cyc-lib/brick_c.cys BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/brick_c.cys --- ORIG/brickos-0.2.6.10/cyc-lib/brick_c.cys 1969-12-31 17:00:00.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/brick_c.cys 2003-11-13 13:24:01.000000000 -0700 @@ -0,0 +1,462 @@ +conio.h: +hstub { + extern "C include" { + void delay(unsigned); + void cputc_native_0(char); + void cputc_native_1(char); + void cputc_native_2(char); + void cputc_native_3(char); + void cputc_native_4(char); + void cputc_native_5(char); + void cputc_native(char, int); + void cputw(unsigned); + void cls(); + + extern const char hex_display_codes[]; + extern const char ascii_display_codes[]; + + static inline void cputc_hex_0(unsigned nibble) + { + cputc_native_0(hex_display_codes[(nibble) & 0x0f]); + } + + static inline void cputc_hex_1(unsigned nibble) + { + cputc_native_1(hex_display_codes[(nibble) & 0x0f]); + } + + static inline void cputc_hex_2(unsigned nibble) + { + cputc_native_2(hex_display_codes[(nibble) & 0x0f]); + } + + static inline void cputc_hex_3(unsigned nibble) + { + cputc_native_3(hex_display_codes[(nibble) & 0x0f]); + } + + static inline void cputc_hex_4(unsigned nibble) + { + cputc_native_4(hex_display_codes[(nibble) & 0x0f]); + } + + static inline void cputc_hex_5(unsigned nibble) + { + cputc_native_5(hex_display_codes[(nibble) & 0x0f]); + } + + static inline void cputc_hex(char c, int pos) + { + cputc_native(hex_display_codes[(c) & 0x7f], pos); + } + + static inline void cputc_0(unsigned c) + { + cputc_native_0(ascii_display_codes[(c) & 0x7f]); + } + + static inline void cputc_1(unsigned c) + { + cputc_native_1(ascii_display_codes[(c) & 0x7f]); + } + + static inline void cputc_2(unsigned c) + { + cputc_native_2(ascii_display_codes[(c) & 0x7f]); + } + + static inline void cputc_3(unsigned c) + { + cputc_native_3(ascii_display_codes[(c) & 0x7f]); + } + + static inline void cputc_4(unsigned c) + { + cputc_native_4(ascii_display_codes[(c) & 0x7f]); + } + + static inline void cputc_5(unsigned c) + { + cputc_native_5(ascii_display_codes[(c) & 0x7f]); + } + + static inline void cputc(char c, int pos) + { + cputc_native(ascii_display_codes[(c) & 0x7f], pos); + } + + } export { + delay, + cputc_native_0, + cputc_native_1, + cputc_native_2, + cputc_native_3, + cputc_native_4, + cputc_native_5, + cputc_native, + cputw, + cls, + cputc_hex_0, + cputc_hex_1, + cputc_hex_2, + cputc_hex_3, + cputc_hex_4, + cputc_hex_5, + cputc_hex, + cputc_0, + cputc_1, + cputc_2, + cputc_3, + cputc_4, + cputc_5, + cputc + } +} +hstub { + extern void cputs(const char@); +} +cycstub { + namespace Cconio { + extern "C" void cputs(const char@); + } + void cputs(const char@s) { + Cconio::cputs(s); + } +} +; +dkey.h: +include { + KEY_ONOFF + KEY_RUN + KEY_VIEW + KEY_PRGM + KEY_ANY +} +hstub { +#include + extern "C include" { + extern volatile unsigned char dkey_multi; + extern volatile unsigned char dkey; + + wakeup_t dkey_pressed(wakeup_t); + wakeup_t dkey_released(wakeup_t); + int getchar(); + } +} +; +dlcd.h: +include { + LCD_ARMS + LCD_BODY + LCD_1LEG + LCD_2LEGS + + LCD_0_TOP + LCD_0_MID + LCD_0_BOT + LCD_0_TOPR + LCD_0_BOTR + LCD_0_TOPL + LCD_0_BOTL + + LCD_1_TOP + LCD_1_MID + LCD_1_BOT + LCD_1_TOPR + LCD_1_BOTR + LCD_1_TOPL + LCD_1_BOTL + + LCD_2_TOP + LCD_2_MID + LCD_2_BOT + LCD_2_TOPR + LCD_2_BOTR + LCD_2_TOPL + LCD_2_BOTL + LCD_2_DOT + + LCD_3_TOP + LCD_3_MID + LCD_3_BOT + LCD_3_TOPR + LCD_3_BOTR + LCD_3_TOPL + LCD_3_BOTL + LCD_3_DOT + + LCD_4_TOP + LCD_4_MID + LCD_4_BOT + LCD_4_TOPR + LCD_4_BOTR + LCD_4_TOPL + LCD_4_BOTL + LCD_4_DOT + + LCD_5_MID + + LCD_A_SELECT + LCD_A_LEFT + LCD_A_RIGHT + + LCD_B_SELECT + LCD_B_LEFT + LCD_B_RIGHT + + LCD_C_SELECT + LCD_C_LEFT + LCD_C_RIGHT + + LCD_S1_SELECT + LCD_S1_ACTIVE + + LCD_S2_SELECT + LCD_S2_ACTIVE + + LCD_S3_SELECT + LCD_S3_ACTIVE + + LCD_CIRCLE_0 + LCD_CIRCLE_1 + LCD_CIRCLE_2 + LCD_CIRCLE_3 + + LCD_DOT_0 + LCD_DOT_1 + LCD_DOT_2 + LCD_DOT_3 + LCD_DOT_4 + + LCD_IR_LOWER + LCD_IR_UPPER + + LCD_BATTERY_X + + LCD_EMPTY_1 + LCD_EMPTY_2 + + dlcd_show + dlcd_hide + dlcd_store + + BYTE_OF + BIT_OF +} +; +dmotor.h: +include { + MotorDirection + MotorState + MIN_SPEED + MAX_SPEED +} +hstub { + extern "C include" { + extern const unsigned char dm_a_pattern[4], + dm_b_pattern[4], + dm_c_pattern[4]; + extern MotorState dm_a; + extern MotorState dm_b; + extern MotorState dm_c; + + extern void motor_a_dir(MotorDirection); + extern void motor_b_dir(MotorDirection); + extern void motor_c_dir(MotorDirection); + + static inline void motor_a_speed(unsigned char speed) + { + dm_a.access.c.delta = speed; + } + + static inline void motor_b_speed(unsigned char speed) + { + dm_b.access.c.delta = speed; + } + + static inline void motor_c_speed(unsigned char speed) + { + dm_c.access.c.delta = speed; + } + + } export { + dm_a_pattern, + dm_b_pattern, + dm_c_pattern, + dm_a, + dm_b, + dm_c, + motor_a_dir, + motor_b_dir, + motor_c_dir, + motor_a_speed, + motor_b_speed, + motor_c_speed + } +} +; +dsensor.h: +include { + LIGHT_RAW_BLACK + LIGHT_RAW_WHITE + LIGHT + LIGHT_MAX + TOUCH + ds_scale + ds_unscale +} +hstub { + extern "C include" { + extern volatile unsigned int AD_A; + extern volatile unsigned int AD_B; + extern volatile unsigned int AD_C; + extern volatile unsigned int AD_D; + + extern volatile unsigned char PORT6; + + extern unsigned char ds_activation; //!< activation bitmask + + extern unsigned char ds_rotation; //!< rotation bitmask + + extern volatile int ds_rotations[3]; + +#define SENSOR_1 AD_C //!< Sensor on input pad 1 +#define SENSOR_2 AD_B //!< Sensor on input pad 2 +#define SENSOR_3 AD_A //!< Sensor on input pad 3 +#define BATTERY AD_D //!< Battery sensor + +#define LIGHT_1 LIGHT(SENSOR_1) //!< light sensor on input 1 +#define LIGHT_2 LIGHT(SENSOR_2) //!< light sensor on input 2 +#define LIGHT_3 LIGHT(SENSOR_3) //!< light sensor on input 3 + +#define ROTATION_1 (ds_rotations[2]) //!< rotation sensor on input 1 +#define ROTATION_2 (ds_rotations[1]) //!< rotation sensor on input 2 +#define ROTATION_3 (ds_rotations[0]) //!< rotation sensor on input 3 + +#define TOUCH_1 TOUCH(SENSOR_1) //!< touch sensor on input 1 +#define TOUCH_2 TOUCH(SENSOR_2) //!< touch sensor on input 2 +#define TOUCH_3 TOUCH(SENSOR_3) //!< touch sensor on input 3 + + static inline void ds_active(volatile unsigned *sensor) + { + if (sensor == &AD_A) + __asm__ ( "bset %0,@%1" : : "i" (0),"r" (&ds_activation)); + else if (sensor == &AD_B) + __asm__ ( "bset %0,@%1" : : "i" (1),"r" (&ds_activation)); + else if (sensor == &AD_C) + __asm__ ( "bset %0,@%1" : : "i" (2),"r" (&ds_activation)); + } + + static inline void ds_passive(volatile unsigned *sensor) + { + if (sensor == &AD_A) { + __asm__ ( "bclr %0,@%1" : : "i" (0),"r" (&ds_activation)); + __asm__ ( "bclr %0,@%1" : : "i" (0),"r" (&PORT6)); + } else if (sensor == &AD_B) { + __asm__ ( "bclr %0,@%1" : : "i" (1),"r" (&ds_activation)); + __asm__ ( "bclr %0,@%1" : : "i" (1),"r" (&PORT6)); + } else if (sensor == &AD_C) { + __asm__ ( "bclr %0,@%1" : : "i" (2),"r" (&ds_activation)); + __asm__ ( "bclr %0,@%1" : : "i" (2),"r" (&PORT6)); + } + } + + extern void ds_rotation_set(volatile unsigned *sensor, int pos); + + + static inline void ds_rotation_on(volatile unsigned *sensor) + { + if (sensor == &AD_A) + __asm__ ( "bset %0,@%1" : : "i" (0),"r" (&ds_rotation)); + else if (sensor == &AD_B) + __asm__ ( "bset %0,@%1" : : "i" (1),"r" (&ds_rotation)); + else if (sensor == &AD_C) + __asm__ ( "bset %0,@%1" : : "i" (2),"r" (&ds_rotation)); + } + + + static inline void ds_rotation_off(volatile unsigned *sensor) + { + if (sensor == &AD_A) + __asm__ ( "bclr %0,@%1" : : "i" (0),"r" (&ds_rotation)); + else if (sensor == &AD_B) + __asm__ ( "bclr %0,@%1" : : "i" (1),"r" (&ds_rotation)); + else if (sensor == &AD_C) + __asm__ ( "bclr %0,@%1" : : "i" (2),"r" (&ds_rotation)); + } + } export { + AD_A, + AD_B, + AD_C, + AD_D, + ds_activation, + ds_rotation, + ds_rotations, + ds_active, + ds_passive, + ds_rotation_set, + ds_rotation_on, + ds_rotation_off + } +} +; + +time.h: +include { + TICK_IN_MS + TICKS_PER_SEC + SECS_TO_TICKS + MSECS_TO_TICKS + time_t +} +hstub { + extern "C" { + time_t get_system_up_time(void); + } +} +; +tm.h: +hstub { + extern "C" { + extern tdata_t *ctid; + } +#define shutdown_requested() ((ctid->tflags & T_SHUTDOWN) != 0) +} +include { + PRIO_LOWEST + PRIO_NORMAL + PRIO_HIGHEST + T_DEAD + T_ZOMBIE + T_WAITING + T_SLEEPING + T_RUNNING + T_KERNEL + T_USER + T_IDLE + T_SHUTDOWN + DEFAULT_STACK_SIZE + tdata_t + tstate_t + tflags_t + priority_t + wakeup_t + tid_t +} +; +unistd.h: +hstub { +#include + extern "C" { + void exit(int) __attribute__((noreturn)); + void yield(void); + wakeup_t wait_event(wakeup_t(@) (wakeup_t), wakeup_t); + unsigned int sleep(unsigned int); + unsigned int msleep(unsigned int); + void shutdown_task(tid_t); + void shutdown_tasks(tflags_t); + void kill(tid_t); + void killall(priority_t); + } +} +; diff -Naur ORIG/brickos-0.2.6.10/cyc-lib/Makefile BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/Makefile --- ORIG/brickos-0.2.6.10/cyc-lib/Makefile 1969-12-31 17:00:00.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/Makefile 2003-11-13 13:24:01.000000000 -0700 @@ -0,0 +1,57 @@ +### ========================================================================== +### FILE: cyc-lib/Makefile - make the Cyclone runtime and libraries +### brickOS - the independent LEGO Mindstorms OS +### -------------------------------------------------------------------------- + + +include ../Makefile.common + +# Add config.h to include path +CINC += -I$(BRICKOS_ROOT)/boot + +CYCLONE_SRC= +BUILDLIB=$(CYCLONE_SRC)/bin/buildlib -b $(H8_ARCH) $(CINC) +BUILDSPECS=$(CYCLONE_SRC)/config/buildspecs -b $(H8_ARCH) + +cyc-lib: \ + precore_c.h \ + cycspecs \ + cyc_setjmp.h \ + libcyc.a \ + nogc.a \ + runtime_cyc.o + +precore_c.h: $(CYCLONE_SRC)/bin/genfiles/precore_c.h + -mkdir include + cp $< $@ + +cycspecs: + $(BUILDSPECS)> $@ + +cyc_setjmp.h: precore_c.h brick_c.cys + $(BUILDLIB) -d include -setjmp > $@ + $(BUILDLIB) -d include brick_c.cys + +nogc.a: nogc.o + -rm $@ + $(AR) rc $@ $< + $(RANLIB) $@ + +include/cycstubs.o: include/cycstubs.cyc + $(CYCLONE) -B. -Iinclude -c -o $@ $< + +libcyc.a: include/cycstubs.o + -rm $@ + $(AR) rc $@ $< + $(RANLIB) $@ + +clean: + -rm -rf include + -rm precore_c.h cycspecs cyc_setjmp.h nogc.a libcyc.a *.o + +.PHONY: cyc-lib clean + + +### -------------------------------------------------------------------------- +### End of FILE: cyc-lib/Makefile +### ========================================================================== diff -Naur ORIG/brickos-0.2.6.10/cyc-lib/nogc.c BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/nogc.c --- ORIG/brickos-0.2.6.10/cyc-lib/nogc.c 1969-12-31 17:00:00.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/nogc.c 2003-11-13 13:24:01.000000000 -0700 @@ -0,0 +1,80 @@ +/* This file is part of the Cyclone Library. + Copyright (C) 2001 AT&T + + This library is free software; you can redistribute it and/or it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place, Suite + 330, Boston, MA 02111-1307 USA. */ + +//* +//* Oct. 20, 2003 +//* Zhongxi Shen, School of Computing, University of Utah +//* Modify it to fit BrickOS for Lego Mindstorms +//* + + +#include //* needed for size_t +#include + +static size_t last_alloc_bytes = 0; + +#define malloc_sizeb(p,n) (last_alloc_bytes = n) + +/* hack: assumes this is called immediately after an allocation */ +size_t GC_size(void *x) { + return last_alloc_bytes; +} + +size_t GC_get_heap_size() { + return 0; +} + +size_t GC_get_free_bytes() { + return 0; +} + +/* total number of bytes allocated */ +static size_t total_bytes_allocd = 0; + +void *GC_malloc(int x) { + // FIX: I'm calling calloc to ensure the memory is zero'd. This + // is because I had to define GC_calloc in runtime_cyc.c + void *p = (void*)calloc(sizeof(char),x); + total_bytes_allocd += malloc_sizeb(p,x); + return p; +} + +void *GC_malloc_atomic(int x) { + // FIX: I'm calling calloc to ensure the memory is zero'd. This + // is because I had to define GC_calloc in runtime_cyc.c + void *p = (void*)calloc(sizeof(char),x); + total_bytes_allocd += malloc_sizeb(p,x); + return p; +} + +void GC_free(void *x) { + free(x); +} + +unsigned int GC_gc_no = 0; +int GC_dont_expand = 0; +int GC_use_entire_heap = 0; + +size_t GC_get_total_bytes() { + return total_bytes_allocd; +} + +void GC_set_max_heap_size(unsigned int sz) { + return; +} + diff -Naur ORIG/brickos-0.2.6.10/cyc-lib/runtime_cyc.c BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/runtime_cyc.c --- ORIG/brickos-0.2.6.10/cyc-lib/runtime_cyc.c 1969-12-31 17:00:00.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/cyc-lib/runtime_cyc.c 2003-11-13 13:24:01.000000000 -0700 @@ -0,0 +1,704 @@ +/* This file is part of the Cyclone Library. + Copyright (C) 2001 Greg Morrisett, AT&T + + This library is free software; you can redistribute it and/or it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place, Suite + 330, Boston, MA 02111-1307 USA. */ + +// This is the C "runtime library" to be used with the output of the +// Cyclone to C translator + +//* +//* November, 2003 +//* Zhongxi Shen, School of Computing, University of Utah +//* Modify it to fit BrickOS for Lego Mindstorms +//* + +//* no file IO in BrickOS, all relavent part deleted + +#include // for memcpy, memset +#include +#include // for clock() +#include //* for exit() + +// The C include file precore_c.h is produced (semi) automatically +// from the Cyclone include file core.h. Note, it now includes +// the contents of cyc_include.h + +/* RUNTIME_CYC defined to prevent including parts of precore_c.h + that might cause problems, particularly relating to region profiling */ +#define RUNTIME_CYC +#include "precore_c.h" +extern void longjmp(jmp_buf,int); // NB precore_c.h defines jmp_buf + +extern void exit(int); + +////////////////////////////////////////////////////////// +// First, definitions for things declared in cyc_include.h +////////////////////////////////////////////////////////// + +// FIX: makes alignment and pointer-size assumptions +// FIX: what about -nocyc??? +char Cyc_Null_Exception[] = "Cyc_Null_Exception"; +struct _xtunion_struct Cyc_Null_Exception_struct = { Cyc_Null_Exception }; +struct _xtunion_struct * Cyc_Null_Exception_val = &Cyc_Null_Exception_struct; +char Cyc_Array_bounds[] = "Cyc_Array_bounds"; +struct _xtunion_struct Cyc_Array_bounds_struct = { Cyc_Array_bounds }; +struct _xtunion_struct * Cyc_Array_bounds_val = &Cyc_Array_bounds_struct; +char Cyc_Match_Exception[] = "Cyc_Match_Exception"; +struct _xtunion_struct Cyc_Match_Exception_struct = { Cyc_Match_Exception }; +struct _xtunion_struct * Cyc_Match_Exception_val = &Cyc_Match_Exception_struct; +char Cyc_Bad_alloc[] = "Cyc_Bad_alloc"; +struct _xtunion_struct Cyc_Bad_alloc_struct = { Cyc_Bad_alloc }; +struct _xtunion_struct * Cyc_Bad_alloc_val = &Cyc_Bad_alloc_struct; + +extern size_t GC_get_heap_size(); +extern size_t GC_get_free_bytes(); +extern size_t GC_get_total_bytes(); + +static int region_get_heap_size(struct _RegionHandle *r); +static int region_get_free_bytes(struct _RegionHandle *r); +static int region_get_total_bytes(struct _RegionHandle *r); + +// FIX: I'm putting GC_calloc and GC_calloc_atomic in here as just +// calls to GC_malloc and GC_malloc_atomic respectively. This will +// *not* work for the nogc option. +void *GC_calloc(unsigned int n, unsigned int t) { + return (void *)GC_malloc(n*t); +} + +void *GC_calloc_atomic(unsigned int n, unsigned int t) { + unsigned int p = n*t; + // the collector does not zero things when you call malloc atomic... + void *res = GC_malloc_atomic(p); + if (res == NULL) { + _throw_badalloc(); + } + memset(res,0,p); //* bzero not supported + return res; +} + +// Need one per thread +static struct _RuntimeStack *_current_handler = NULL; + +// The exception that was thrown +struct _xtunion_struct *_exn_thrown = NULL; + +// create a new handler, put it on the stack, and return it so its +// jmp_buf can be filled in by the caller +void _push_handler(struct _handler_cons * new_handler) { + new_handler->s.tag = 0; + new_handler->s.next = _current_handler; + _current_handler = (struct _RuntimeStack *)new_handler; +} + +void _push_region(struct _RegionHandle * r) { + r->s.tag = 1; + r->s.next = _current_handler; + _current_handler = (struct _RuntimeStack *)r; +} + +// set _current_handler to its n+1'th tail +// Invariant: result is non-null +void _npop_handler(int n) { + if (n<0) { + exit(1); + } + for(; n>=0; n--) { + if(_current_handler == NULL) { + exit(1); + } + if (_current_handler->tag == 1) { + _free_region((struct _RegionHandle *)_current_handler); + //} else { + //fprintf(stderr,"popping handler %x\n",(unsigned int)_current_handler); + } + _current_handler = _current_handler->next; + } +} + +void _pop_handler() { + if (_current_handler == NULL || _current_handler->tag != 0) { + //*fprintf(stderr,"internal error: _pop_handler"); + exit(1); + } + _npop_handler(0); +} +void _pop_region() { + if (_current_handler == NULL || _current_handler->tag != 1) { + //*fprintf(stderr,"internal error: _pop_region"); + exit(1); + } + _npop_handler(0); +} + +extern int Cyc_Execinfo_bt(void); +static struct _handler_cons top_handler; +static int in_backtrace = 0; // avoid infinite exception chain +static const char *_exn_filename = "?"; +static unsigned _exn_lineno = 0; + +const char *Cyc_Core_get_exn_filename() { + return _exn_filename; +} +int Cyc_Core_get_exn_lineno() { + return _exn_lineno; +} +const char *Cyc_Core_get_exn_name(struct _xtunion_struct *x) { + return x->tag; +} +int _throw_fn(void* e, const char *filename, unsigned lineno) {// FIX: use struct _xtunion_struct * ?? + struct _handler_cons *my_handler; + while (_current_handler->tag != 0) { + if (_current_handler->tag == 1) + _pop_region(); + } + my_handler = (struct _handler_cons *)_current_handler; + _pop_handler(); + _exn_thrown = e; + _exn_filename = filename; + _exn_lineno = lineno; + longjmp(my_handler->handler,1); +} + +/* re-throw an exception, but keep the filename and lineno info */ +void Cyc_Core_rethrow(void *e) { + _throw_fn(e, _exn_filename, _exn_lineno); +} + +#ifdef throw +#undef throw +#endif +int throw(void *e) { _throw_fn(e,"?",0); } + +int _throw_null_fn(const char *filename, unsigned lineno) { + _throw_fn(Cyc_Null_Exception_val,filename,lineno); +} +int _throw_arraybounds_fn(const char *filename, unsigned lineno) { + _throw_fn(Cyc_Array_bounds_val,filename,lineno); +} +int _throw_badalloc_fn(const char *filename, unsigned lineno) { + _throw_fn(Cyc_Bad_alloc_val,filename,lineno); +} +int _throw_match_fn(const char *filename, unsigned lineno) { + _throw_fn(Cyc_Match_Exception_val,filename,lineno); +} + +struct _dyneither_ptr wrap_Cstring_as_string(Cstring s, size_t len) { + struct _dyneither_ptr str; + if (s == NULL) { + str.base = str.curr = str.last_plus_one = NULL; + } else { + int slen = strlen(s)+1; + if (len == -1) + len = slen; + else if (len > slen) + _throw_arraybounds(); /* FIX: pick better exception */ + str.base = str.curr = s; + str.last_plus_one = s + len; + } + return str; +} + +// trusted---the length field is not verified to be correct +struct _dyneither_ptr wrap_Cbuffer_as_buffer(Cstring s, size_t len) { + struct _dyneither_ptr str; + if (s == NULL) { + str.base = str.curr = str.last_plus_one = NULL; + } else { + str.base = str.curr = s; + str.last_plus_one = s + len; + } + return str; +} + +struct _dyneither_ptr Cstring_to_string(Cstring s) { + struct _dyneither_ptr str; + if (s == NULL) { + str.base = str.curr = str.last_plus_one = NULL; + } + else { + int sz = strlen(s)+1; + str.curr = (char *)_cycalloc_atomic(sz); + if (str.curr == NULL) + _throw_badalloc(); + str.base = str.curr; + str.last_plus_one = str.curr + sz; + + // Copy the string in case the C code frees it or mangles it + str.curr[--sz] = '\0'; + while(--sz>=0) + str.curr[sz]=s[sz]; + } + return str; +} + +Cstring string_to_Cstring(struct _dyneither_ptr s) { + int i; + char *contents = s.curr; + size_t sz = s.last_plus_one - s.curr; + char *str; + + if (s.curr == NULL) return NULL; + + if (s.curr >= s.last_plus_one || s.curr < s.base) + _throw_arraybounds(); + // check that there's a '\0' somewhere in the string -- if not, + // throw an exception. + for (str = s.last_plus_one-1; str >= contents; str--) { + if (*str == '\0') return contents; + } + _throw_null(); +} + +// Returns the size of an array from the current pointer back to +// its starting point. If the curr pointer = start pointer, or +// the curr pointer is out of bounds, then this is 0. +unsigned int arr_prevsize(struct _dyneither_ptr arr,size_t elt_sz) { + unsigned char *_get_arr_size_curr=arr.curr; + unsigned char *_get_arr_size_base=arr.base; + return + (_get_arr_size_curr < _get_arr_size_base || + _get_arr_size_curr >= arr.last_plus_one) ? 0 : + ((_get_arr_size_curr - _get_arr_size_base) / (elt_sz)); +} +/////////////////////////////////////////////// +// Regions + +#ifdef CYC_REGION_PROFILE +int rgn_total_bytes = 0; +static int rgn_freed_bytes = 0; +static int heap_total_bytes = 0; +static int heap_total_atomic_bytes = 0; +static int unique_total_bytes = 0; +static int unique_freed_bytes = 0; +static int refcnt_total_bytes = 0; +static int refcnt_freed_bytes = 0; +#endif + + +// exported in core.h +#define CYC_CORE_HEAP_REGION (NULL) +#define CYC_CORE_UNIQUE_REGION ((struct _RegionHandle *)1) +#define CYC_CORE_REFCNT_REGION ((struct _RegionHandle *)2) +struct _RegionHandle *Cyc_Core_heap_region = CYC_CORE_HEAP_REGION; +struct _RegionHandle *Cyc_Core_unique_region = CYC_CORE_UNIQUE_REGION; +struct _RegionHandle *Cyc_Core_refcnt_region = CYC_CORE_REFCNT_REGION; + +/////// UNIQUE REGION ////////// + +// for freeing unique pointers; might want to make this "free" +// eventually (but currently this is set to a no-op in libc.cys). +// Note that this is not recursive; it assumes that programmer +// has freed nested pointers (otherwise will be grabbed by the GC). +void Cyc_Core_ufree(struct _dyneither_ptr ptr) { + if (ptr.base == NULL) return; // eventually make not-null type + else { +#ifdef CYC_REGION_PROFILE + unsigned int sz = GC_size(ptr.base); + unique_freed_bytes += sz; + // output special "alloc" event here, where we have a negative size + if (alloc_log != NULL) { + fprintf(alloc_log,"%u @\tunique\talloc\t-%d\t%d\t%d\t%d\t%x\n", + clock(), + sz, + region_get_heap_size(CYC_CORE_UNIQUE_REGION), + region_get_free_bytes(CYC_CORE_UNIQUE_REGION), + region_get_total_bytes(CYC_CORE_UNIQUE_REGION), + (unsigned int)ptr.base); + } + // FIX: JGM -- I moved this before the endif -- it was after, + // but I'm pretty sure we don't need this unless we're profiling. + GC_register_finalizer_no_order(ptr.base,NULL,NULL,NULL,NULL); +#endif + GC_free(ptr.base); + ptr.base = ptr.curr = ptr.last_plus_one = NULL; // not really necessary... + } +} + +/////// REFERENCE-COUNTED REGION ////////// + +static int *get_refcnt(struct _dyneither_ptr ptr) { + if (ptr.base == NULL) return NULL; + else { + int *res = (int *)(ptr.base - sizeof(int)); + return res; + } +} + +int Cyc_Core_refptr_count(struct _dyneither_ptr ptr) { + int *cnt = get_refcnt(ptr); + if (cnt != NULL) return *cnt; + else return 0; +} + +struct _dyneither_ptr Cyc_Core_alias_refptr(struct _dyneither_ptr ptr) { + int *cnt = get_refcnt(ptr); + if (cnt != NULL) *cnt = *cnt + 1; + return ptr; +} + +void Cyc_Core_drop_refptr(struct _dyneither_ptr ptr) { + int *cnt = get_refcnt(ptr); + if (cnt != NULL) { + *cnt = *cnt - 1; + if (*cnt == 0) { // no more references + GC_free(ptr.base - sizeof(int)); + ptr.base = ptr.curr = ptr.last_plus_one = NULL; // not necessary... + } + } +} + +///////////////////////////////////////////////////////////////////// + +// defined below so profiling macros work +struct _RegionHandle _new_region(const char *); +// struct _RegionHandle _new_region(); +static void grow_region(struct _RegionHandle *r, unsigned int s); + +// minimum page size for a region +#define CYC_MIN_REGION_PAGE_SIZE 480 //* change for BrickOS ?? + +// controls the default page size for a region +static size_t default_region_page_size = CYC_MIN_REGION_PAGE_SIZE; + +// set the default region page size -- returns false and has no effect +// if s is not at least CYC_MIN_REGION_PAGE_SIZE +bool Cyc_set_default_region_page_size(size_t s) { + if (s < CYC_MIN_REGION_PAGE_SIZE) + return 0; + default_region_page_size = s; + return 1; +} + +// argc is redundant +struct _tagged_argv { + struct _dyneither_ptr *base; + struct _dyneither_ptr *curr; + struct _dyneither_ptr *last_plus_one; +}; + +extern int Cyc_main(int argc, struct _dyneither_ptr argv); + +int main(int argc, char **argv) { + // install outermost exception handler + if (setjmp(top_handler.handler)) { + //* FIX_BRICK: do sth. on the brick, e.g. beep + return 1; + } + + _push_handler(&top_handler); + + // convert command-line args to Cyclone strings -- we add an extra + // NULL to the end of the argv so that people can step through argv + // until they hit NULL. + {struct _tagged_argv args; + struct _dyneither_ptr args_p; + int i, result; + args.curr = + (struct _dyneither_ptr *)GC_malloc((argc+1)*sizeof(struct _dyneither_ptr)); + args.base = args.curr; + args.last_plus_one = args.curr + argc + 1; + for(i = 0; i < argc; ++i) + args.curr[i] = Cstring_to_string(argv[i]); + // plug in final NULL + args.curr[argc].base = 0; + args.curr[argc].curr = 0; + args.curr[argc].last_plus_one = 0; + args_p.curr = (unsigned char *)args.curr; + args_p.base = args_p.curr; + args_p.last_plus_one = (unsigned char *)args.last_plus_one; + result = Cyc_main(argc, args_p); + return result; + } +} + +static void grow_region(struct _RegionHandle *r, unsigned int s) { + struct _RegionPage *p; + unsigned int prev_size, next_size; + + prev_size = r->last_plus_one - ((char *)r->curr + sizeof(struct _RegionPage)); + next_size = prev_size * 2; + + if (next_size < s) + next_size = s + default_region_page_size; + + // Note, we call calloc here to ensure we get zero-filled pages + p = GC_calloc(sizeof(struct _RegionPage) + next_size,1); + if (!p) { + //*fprintf(stderr,"grow_region failure"); + _throw_badalloc(); + } + p->next = r->curr; + r->curr = p; + r->offset = ((char *)p) + sizeof(struct _RegionPage); + r->last_plus_one = r->offset + next_size; +} + +// better not get called with the heap or unique regions ... +static void _get_first_region_page(struct _RegionHandle *r, unsigned int s) { + struct _RegionPage *p; + unsigned int page_size = + default_region_page_size < s ? s : default_region_page_size; + p = (struct _RegionPage *)GC_calloc(sizeof(struct _RegionPage) + + page_size,1); + if (p == NULL) + _throw_badalloc(); + p->next = NULL; + r->curr = p; + r->offset = ((char *)p) + sizeof(struct _RegionPage); + r->last_plus_one = r->offset + page_size; +} + +// allocate s bytes within region r +void * _region_malloc(struct _RegionHandle *r, unsigned int s) { + char *result; + if (r > (struct _RegionHandle *)_CYC_MAX_REGION_CONST) { +#ifndef CYC_NOALIGN + // round s up to the nearest _CYC_MIN_ALIGNMENT value + s = (s + _CYC_MIN_ALIGNMENT - 1) & (~(_CYC_MIN_ALIGNMENT - 1)); +#endif + // if no page yet, then fetch one + if (r->curr == 0) { + _get_first_region_page(r,s); + result = r->offset; + } else { + result = r->offset; + // else check for space on the current page + if (s > (r->last_plus_one - result)) { + grow_region(r,s); + result = r->offset; + } + } + r->offset = result + s; + return (void *)result; + } else if (r != CYC_CORE_REFCNT_REGION) { + result = GC_malloc(s); + if(!result) + _throw_badalloc(); + return (void *)result; + } + else { // (r == CYC_CORE_REFCNT_REGION) + // need to add a word for the reference count. We use a word to + // keep the resulting memory word-aligned. Then bump the pointer. + // FIX: probably need to keep it double-word aligned! + result = GC_malloc(s+sizeof(int)); + if(!result) + _throw_badalloc(); + *(int *)result = 1; + result += sizeof(int); + return (void *)result; + } +} + +// allocate s bytes within region r +void * _region_calloc(struct _RegionHandle *r, unsigned int n, unsigned int t) +{ + unsigned int s = n*t; + char *result; + if (r > (struct _RegionHandle *)_CYC_MAX_REGION_CONST) { + // round s up to the nearest _CYC_MIN_ALIGNMENT value +#ifndef CYC_NOALIGN + s = (s + _CYC_MIN_ALIGNMENT - 1) & (~(_CYC_MIN_ALIGNMENT - 1)); +#endif + // if no page yet, then fetch one + if (r->curr == 0) { + _get_first_region_page(r,s); + result = r->offset; + } else { + result = r->offset; + // else check for space on the current page + if (s > (r->last_plus_one - result)) { + grow_region(r,s); + result = r->offset; + } + } + r->offset = result + s; + return (void *)result; + } else if (r != CYC_CORE_REFCNT_REGION) { + // allocate in the heap + result = GC_calloc(n,t); + if(!result) + _throw_badalloc(); + return result; + } else { // r == CYC_CORE_REFCNT_REGION) + // allocate in the heap + 1 word for the refcount + result = GC_calloc(n*t+sizeof(int),1); + if(!result) + _throw_badalloc(); + *(int *)result = 1; + result += sizeof(int); + return result; + } +} + +// allocate a new page and return a region handle for a new region. +struct _RegionHandle _new_region(const char *rgn_name) { + struct _RegionHandle r; + + /* we're now lazy about allocating a region page */ + //struct _RegionPage *p; + + // we use calloc to make sure the memory is zero'd + //p = (struct _RegionPage *)GC_calloc(sizeof(struct _RegionPage) + + // default_region_page_size,1); + //if (p == NULL) + // _throw_badalloc(); + //p->next = NULL; + r.s.tag = 1; + r.s.next = NULL; + r.curr = 0; + r.offset = 0; + r.last_plus_one = 0; + //r.offset = ((char *)p) + sizeof(struct _RegionPage); + //r.last_plus_one = r.offset + default_region_page_size; + return r; +} + +// free all the resources associated with a region (except the handle) +// (assumes r is not heap or unique region) +void _free_region(struct _RegionHandle *r) { + struct _DynRegionHandle *d; + struct _RegionPage *p; + + /* free pages */ + p = r->curr; + while (p != NULL) { + struct _RegionPage *n = p->next; + GC_free(p); + p = n; + } + r->curr = 0; + r->offset = 0; + r->last_plus_one = 0; +} + +// reset the region by freeing its pages and then reallocating a fresh page. +// (assumes r is not heap or unique region) +void _reset_region(struct _RegionHandle *r) { + _free_region(r); + *r = _new_region(NULL); +} + + +// Dynamic Regions +// Note that struct Cyc_Core_DynamicRegion is defined in cyc_include.h. + +// We use this struct when returning a newly created dynamic region. +// The wrapper is needed because the Cyclone interface uses an existential. +struct Cyc_Core_NewDynamicRegion { + struct Cyc_Core_DynamicRegion *key; +}; + +// Create a new dynamic region and return a unique pointer for the key. +struct Cyc_Core_NewDynamicRegion Cyc_Core_new_ukey() { + struct Cyc_Core_NewDynamicRegion res; + res.key = GC_malloc(sizeof(struct Cyc_Core_DynamicRegion)); + if (!res.key) + _throw_badalloc(); + res.key->h = _new_region("dynamic_unique"); + return res; +} +// Destroy a dynamic region, given the unique key to it. +void Cyc_Core_free_ukey(struct Cyc_Core_DynamicRegion *k) { + _free_region(&k->h); + GC_free(k); +} + +// Create a new dynamic region and return a reference-counted pointer +// for the key. +struct Cyc_Core_NewDynamicRegion Cyc_Core_new_rckey() { + struct Cyc_Core_NewDynamicRegion res; + int *krc = GC_malloc(sizeof(int)+sizeof(struct Cyc_Core_DynamicRegion)); + if (!krc) + _throw_badalloc(); + *krc = 1; + res.key = (struct Cyc_Core_DynamicRegion *)(krc + 1); + res.key->h = _new_region("dynamic_refcnt"); + return res; +} +// Drop a reference for a dynamic region, possibly freeing it. +void Cyc_Core_free_rckey(struct Cyc_Core_DynamicRegion *k) { + int *p = ((int *)k) - 1; + unsigned c = (*p) - 1; + if (c >= *p) { + exit(1); + } + *p = c; + if (c == 0) { + _free_region(&k->h); + GC_free(p); + } +} + +// Open a key (unique or reference-counted), extract the handle +// for the dynamic region, and pass it along with env to the +// body function pointer, returning the result. +void *Cyc_Core_open_region(struct Cyc_Core_DynamicRegion *k, + void *env, + void *body(struct _RegionHandle *h, + void *env)) { + return body(&k->h,env); +} + +static int region_get_heap_size(struct _RegionHandle *r) { + if (r > (struct _RegionHandle *)_CYC_MAX_REGION_CONST) { + unsigned used_bytes = r->used_bytes; + return used_bytes; + } + else + return GC_get_heap_size(); +} + +static int region_get_free_bytes(struct _RegionHandle *r) { + if (r > (struct _RegionHandle *)_CYC_MAX_REGION_CONST) { + struct _RegionPage *p = r->curr; + unsigned free_bytes = r->last_plus_one - r->offset; + return free_bytes; + } + else + return GC_get_free_bytes(); +} + +static int region_get_total_bytes(struct _RegionHandle *r) { + if (r > (struct _RegionHandle *)_CYC_MAX_REGION_CONST) { + struct _RegionPage *p = r->curr; + unsigned used_bytes = r->used_bytes; + unsigned wasted_bytes = r->wasted_bytes; + unsigned free_bytes = r->last_plus_one - r->offset; + return (used_bytes - wasted_bytes - free_bytes); + } + else { + return GC_get_total_bytes(); + } +} + + +int region_used_bytes(struct _RegionHandle *r) { + return region_get_heap_size(r); +} +int region_free_bytes(struct _RegionHandle *r) { + return region_get_free_bytes(r); +} +int region_alloc_bytes(struct _RegionHandle *r) { + return region_get_total_bytes(r); +} + +// Called from gc/alloc.c for allocation profiling. Must be +// defined even if CYC_REGION_PROFILE is not. +void CYCALLOCPROFILE_GC_add_to_heap(void *p,unsigned long bytes) { +} +void CYCALLOCPROFILE_mark(const char *s) { +} + diff -Naur ORIG/brickos-0.2.6.10/demo/cyclone/helloworld.cyc BRICK-CYCLONE/brickos-0.2.6.10/demo/cyclone/helloworld.cyc --- ORIG/brickos-0.2.6.10/demo/cyclone/helloworld.cyc 1969-12-31 17:00:00.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/demo/cyclone/helloworld.cyc 2003-11-13 13:24:01.000000000 -0700 @@ -0,0 +1,12 @@ +#include +#include + +int main(int argc, char ??argv) { + cputs("hello"); + sleep(1); + cputs("world"); + sleep(1); + cls(); + + return 0; +} diff -Naur ORIG/brickos-0.2.6.10/demo/cyclone/Makefile BRICK-CYCLONE/brickos-0.2.6.10/demo/cyclone/Makefile --- ORIG/brickos-0.2.6.10/demo/cyclone/Makefile 1969-12-31 17:00:00.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/demo/cyclone/Makefile 2003-11-13 13:27:54.000000000 -0700 @@ -0,0 +1,37 @@ +### ========================================================================== +### FILE: demo/cyclone/Makefile - make the Cyclong Language Demo Programs +### brickOS - the independent LEGO Mindstorms OS +### -------------------------------------------------------------------------- + +# name for the brickOS kernel +# #LIBDIR# ### DO NOT REMOVE THIS LINE ### +KERNEL=../../boot/brickOS +CYCLIB=../../cyc-lib + +# extra dynamic sources +DOBJECTS=$(CYCLIB)/runtime_cyc.o $(CYCLIB)/nogc.a $(CYCLIB)/libcyc.a + +include ../../Makefile.common +include ../../Makefile.user + +install uninstall: + @# nothing to do here but do it silently + +# NOTE: --format=1 is not supported on Linux ([ce]tags in emacs2[01] packages) +# please set in your own environment +tag: + -ctags *.c ../include/*.h ../include/*/*.h + -etags *.c ../include/*.h ../include/*/*.h + +clean:: + rm -f *.o *.dis *.dis2 *~ *.bak *.tgz *.s *.ds1 *.ds2 *.dmap *.dcoff + rm -f *.srec *.map *.coff + +realclean:: clean + rm -f *.lx .depend tags TAGS + + +### -------------------------------------------------------------------------- +### End of FILE: demo/cyclone/Makefile +### ========================================================================== + diff -Naur ORIG/brickos-0.2.6.10/demo/cyclone/rover.cyc BRICK-CYCLONE/brickos-0.2.6.10/demo/cyclone/rover.cyc --- ORIG/brickos-0.2.6.10/demo/cyclone/rover.cyc 1969-12-31 17:00:00.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/demo/cyclone/rover.cyc 2003-11-13 13:27:54.000000000 -0700 @@ -0,0 +1,71 @@ +#include +#include + +#include +#include + +//#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// +// Functions +// +/////////////////////////////////////////////////////////////////////////////// + +wakeup_t sensor_press_wakeup(wakeup_t data); + +// the rover driver +// +int main(int argc, char ??argv) { + int dir=0; + + while (!shutdown_requested()) { + motor_a_speed(2*MAX_SPEED/3); // go! + motor_c_speed(2*MAX_SPEED/3); + + motor_a_dir(fwd); + motor_c_dir(fwd); + + cputs("fwwd "); + + if (wait_event(&sensor_press_wakeup, 0) != 0) { + if(SENSOR_1<0xf000) // keep in mind. + dir=0; + else + dir=1; + + // back up + // + motor_a_dir(rev); + motor_c_dir(rev); + + cputs("rev "); + + msleep(500); + + motor_a_speed(MAX_SPEED); // go! + motor_c_speed(MAX_SPEED); + + if(dir==1) { + motor_c_dir(fwd); + cputs("left "); + } else { + motor_a_dir(fwd); + cputs("right"); + } + + msleep(500); + } + } + + return 0; +} + +extern "C" void lcd_refresh(); + +wakeup_t sensor_press_wakeup(wakeup_t data) { + lcd_refresh(); + return (SENSOR_1<0xf000) || (SENSOR_3<0xf000); +} + diff -Naur ORIG/brickos-0.2.6.10/Makefile.common BRICK-CYCLONE/brickos-0.2.6.10/Makefile.common --- ORIG/brickos-0.2.6.10/Makefile.common 2003-02-13 23:03:17.000000000 -0700 +++ BRICK-CYCLONE/brickos-0.2.6.10/Makefile.common 2003-11-13 13:29:42.000000000 -0700 @@ -36,6 +36,7 @@ # BEGIN-configuration insert (do not remove this line) # ------------------------------------------------------- TOOLPREFIX=/usr/h8300-hitachi-hms/bin/h8300-hitachi-hms- +H8_ARCH= SED_SFLAG= EXT= CC=cc @@ -92,6 +93,11 @@ CFLAGS=$(COPT) $(CWARN) $(CINC) $(CDEFINES) CXXFLAGS=-DCXX $(CFLAGS) +CYCINC=-I$(BRICKOS_ROOT)/cyc-lib/include +CYCBIN=-B$(BRICKOS_ROOT)/cyc-lib + +CYCFLAGS=$(COPT) $(CYCINC) $(CYCBIN) + ## ## older options ## @@ -116,8 +122,10 @@ NM=$(TOOLPREFIX)nm OBJCOPY=$(TOOLPREFIX)objcopy OBJDUMP=$(TOOLPREFIX)objdump +RANLIB=$(TOOLPREFIX)ranlib CC=$(TOOLPREFIX)gcc CXX=$(TOOLPREFIX)g++ +CYCLONE=cyclone -b $(H8_ARCH) MERGEMAP =$(BRICKOS_ROOT)/util/merge-map GENLDS =$(BRICKOS_ROOT)/util/genlds @@ -133,6 +141,10 @@ %.o: %.s $(AS) $< -o $@ +# how to compile Cyclone source +%.o: %.cyc + $(CYCLONE) $(CYCFLAGS) -c $< -o $@ + # how to compile C source %.o: %.c $(CC) $(CFLAGS) -c $< -o $@