Initial push of the contents of Dave Hein's latest release.
This commit is contained in:
commit
bdd3741b10
|
@ -0,0 +1,27 @@
|
||||||
|
TARGET = spinsim
|
||||||
|
|
||||||
|
SOURCES = spinsim.c spininterp.c spindebug.c pasmsim.c pasmdebug.c pasmsim2.c pasmdebug2.c eeprom.c debug.c gdb.c
|
||||||
|
OBJECTS = $(SOURCES:.c=.o)
|
||||||
|
|
||||||
|
ifneq ($(OS),msys)
|
||||||
|
SOURCES += conion.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
# I'm not sure why these linker flags were being used but the break the build on Mac OS X so I've
|
||||||
|
# commented them out for the time being
|
||||||
|
#LDFLAGS = -Wl,--relax -Wl,--gc-sections
|
||||||
|
LDFLAGS =
|
||||||
|
OPT := -O3
|
||||||
|
CFLAGS = -c -g -Wall -Wno-format $(OPT) -I/usr/include -D LINUX
|
||||||
|
|
||||||
|
all: $(SOURCES) $(OBJECTS) Makefile
|
||||||
|
$(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET)
|
||||||
|
|
||||||
|
# Compile .c files into objexts .o
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
clean: FORCE
|
||||||
|
rm -f *.o $(TARGET)
|
||||||
|
FORCE:
|
|
@ -0,0 +1,135 @@
|
||||||
|
Spinsim 0.75
|
||||||
|
|
||||||
|
This version of spinsim supports about two-thirds of the opcodes in the P2
|
||||||
|
instruction set. The list of implemented opcodes is shown below, along with
|
||||||
|
the list of opcodes that have not been implemented yet. Spinsim runs in the P1
|
||||||
|
mode by default. It can be set to run in the P2 mode with the -t parameter.
|
||||||
|
|
||||||
|
In the P2 mode, spinsim will load a P2 OBJ file into hub RAM, and start cog 0
|
||||||
|
with the code located at $E00. A simulated serial port is supported by using
|
||||||
|
the -b option. The default baud rate is 115,200, but other rates can be used
|
||||||
|
by specifying it with -b, such as -b9600. The serial port uses pin 31 and 30,
|
||||||
|
just like with P1.
|
||||||
|
|
||||||
|
Spinsim is built using the Makefile, and typing make. I have successfully
|
||||||
|
built and run it under Cygwin and Ubuntu Linux.
|
||||||
|
|
||||||
|
The sample program, pfth.spin can be run by building it with the PNut P2
|
||||||
|
assembler. PNut is contained in the Terasic_Prop2_Emulation zip file,
|
||||||
|
which can be downloaded from the first post in the "HUB EXEC Update Here"
|
||||||
|
thread in the Propeller 2 forum.
|
||||||
|
|
||||||
|
There are two demo programs, which are the pfth Forth interpreter and the
|
||||||
|
p1spin Spin interpreter that runs P1 Spin binaries on the P2 processor.
|
||||||
|
The pfth program is run under spinsim as follows:
|
||||||
|
|
||||||
|
./spinsim -t -b pfth.obj
|
||||||
|
|
||||||
|
p1spin runs at a baud rate of 57600, so it is run as follows:
|
||||||
|
|
||||||
|
./spinsim -t -b57600 p1spin.obj
|
||||||
|
|
||||||
|
Spinsim supports execution from cog memory and hub execution, but it does not
|
||||||
|
support multi-tasking. Only the core processor is supported, and none of the
|
||||||
|
counters, video hardware or cordic hardware is simulated. Support for multi-
|
||||||
|
tasking, peripheral hardware and cordic instructions will be added later.
|
||||||
|
|
||||||
|
Spinsim contains a simple debugger, which is enabled with the -d command-line
|
||||||
|
option. The debugger prints the prompt "DEBUG>" to indicate that it is ready
|
||||||
|
to accept a command. The "help" command will print the following:
|
||||||
|
|
||||||
|
Debug Commands
|
||||||
|
help - Print command list
|
||||||
|
exit - Exit spinsim
|
||||||
|
step - Run one cycle
|
||||||
|
stepx - Run next executed instruction
|
||||||
|
run - Run continuously
|
||||||
|
verbose # - Set verbosity level
|
||||||
|
reboot - Reboot the Prop
|
||||||
|
setbr cog addr - Set breakpoint for cog to addr
|
||||||
|
state cog - Dump cog state
|
||||||
|
|
||||||
|
The "step" command will run one cycle, and the "stepx" command will run any
|
||||||
|
non-executing cycles until it encounters an instruction that is executed.
|
||||||
|
The previous command can be executed again by just pushing the enter key.
|
||||||
|
This is useful for stepping where the "step" command is typed once, and
|
||||||
|
the enter key can then be used to step again.
|
||||||
|
|
||||||
|
The "run" command will run until a breakpoint is encountered or ^] is typed.
|
||||||
|
^] is typed by holding down the control key and pressing the "]" key.
|
||||||
|
While running, spinsim will print out the results of each cycle as
|
||||||
|
controlled by the verbosity level, which is set by the "verbose" command.
|
||||||
|
The verbosity level can also be set with the command-line parameter "-v#".
|
||||||
|
|
||||||
|
The verbosity levels are as follows:
|
||||||
|
|
||||||
|
0 - Disable printing
|
||||||
|
1 - Print only the executed instructions
|
||||||
|
2 - Print only the executed instructions, and show the execution results
|
||||||
|
3 - Print executed and instruction not executed due to condition code
|
||||||
|
4 - Also print instructions invalidated in the pipeline due to jumps
|
||||||
|
5 - Also print instructions that include hub and hardware waits
|
||||||
|
6 - Also print instructions that include icache waits
|
||||||
|
7 - Also print instructions waiting for a pin state
|
||||||
|
8 - Print all cycles, including waitcnt waits
|
||||||
|
|
||||||
|
The verbosity level is entered as a hexadecimal number. If the verbosity level
|
||||||
|
is entered as a single digit it will apply to all cogs. If more than one digit
|
||||||
|
is entered each digit will be used for each cog, starting with cog 0 for the
|
||||||
|
right-most digit. As an example, a value of 456 will cause 6 to be used for
|
||||||
|
cog 0, 5 for cog 1, and 4 for cog 2. All other cogs will use 0.
|
||||||
|
|
||||||
|
|
||||||
|
Implemented Opcodes
|
||||||
|
-------------------
|
||||||
|
abs add addabs addptra addptrb addptrx addptry adds
|
||||||
|
addsx addx and andn augd augs bingry blmask
|
||||||
|
call calla callad callb callbd calld callx callxd
|
||||||
|
cally callyd chkptrx chkptry clkset clracca clraccb clraccs
|
||||||
|
clrb clrp cmp cmpcnt cmps cmpsub cmpsx cmpx
|
||||||
|
cogid coginit cognew cogstop dcachex decd decds decmod
|
||||||
|
decod2 decod3 decod4 decod5 div32 div32u div64 div64d
|
||||||
|
div64u djnz djnzd djz djzd encod fixinda fixindb
|
||||||
|
fixindx frac getacah getacal getacbh getacbl getbyte getcnt
|
||||||
|
getdivq getdivr getmulh getmull getnib getnp getp getptra
|
||||||
|
getptrb getptrx getptry getsqrt getword icachen icachep icachex
|
||||||
|
ijnz ijnzd ijz ijzd incd incds incmod isob
|
||||||
|
jmp jmpd jmpsw jmpswd jnp jnpd jnz jnzd
|
||||||
|
jp jpd jz jzd locbase locbyte lockclr locknew
|
||||||
|
lockret lockset loclong locptra locptrb locword maca macb
|
||||||
|
max maxs mergew min mins mov mul mul32
|
||||||
|
mul32u muxc muxnc muxnz muxz neg negc negnc
|
||||||
|
negnz negz not notb notp offp onecnt or
|
||||||
|
pop popzc push pushzc rcl rcr rdaux rdauxr
|
||||||
|
rdbyte rdbytec rdlong rdlongc rdwide rdwidec rdword rdwordc
|
||||||
|
repd reps ret reta retad retb retbd retd
|
||||||
|
retx retxd rety retyd rev rol ror sar
|
||||||
|
saracca saraccb saraccs setacca setaccb setb setbc setbnc
|
||||||
|
setbnz setbyte setbz setd seti setindb setindx setnib
|
||||||
|
setp setpc setpnc setpnz setptra setptrb setptrx setptry
|
||||||
|
setpz sets setwide setwidz setword setzc seussf seussr
|
||||||
|
shl shr splitw sqrt32 sqrt64 sub subabs subcnt
|
||||||
|
subptra subptrb subptrx subptry subr subs subsx subx
|
||||||
|
sumc sumnc sumnz sumz test testn wait waitcnt
|
||||||
|
waitpeq waitpne wraux wrauxr wrbyte wrlong wrwide wrword
|
||||||
|
xor zercnt
|
||||||
|
|
||||||
|
|
||||||
|
Opcodes Not Implemented
|
||||||
|
-----------------------
|
||||||
|
addphsa addphsb addphss addpix bcdbin binbcd blnpix capctra
|
||||||
|
capctrb capctrs cfgdac0 cfgdac1 cfgdac2 cfgdac3 cfgdacs cfgpins
|
||||||
|
cmpr decpat eswap4 eswap8 getcntx getcosa getcosb getlfsr
|
||||||
|
getphsa getphsb getphza getphzb getpix getqx getqy getqz
|
||||||
|
getsina getsinb grybin incpat jmplist jmptask locinst mergeb
|
||||||
|
mixpix movbyts mulpix packrgb passcnt polctra polctrb polvid
|
||||||
|
qartan qexp qlog qrotate qsincos rolbyte rolnib rolword
|
||||||
|
scl serina serinb serouta seroutb setbyts setctra setctrb
|
||||||
|
setctrs setdac0 setdac1 setdac2 setdac3 setdacs setfrqa setfrqb
|
||||||
|
setfrqs setmap setmix setphsa setphsb setphss setpix setpixa
|
||||||
|
setpixb setpixg setpixr setpixu setpixv setpixw setpixz setpora
|
||||||
|
setporb setporc setpord setqi setqz setrace setsera setserb
|
||||||
|
settask setvid setvidi setvidq setvidy setwava setwavb setwavs
|
||||||
|
setwrds setx setxch setxft splitb subphsa subphsb subphss
|
||||||
|
synctra synctrb taskid testb unpkrgb waitpf waitpr waitpx
|
||||||
|
waitvid
|
|
@ -0,0 +1,136 @@
|
||||||
|
'******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 1.0
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************
|
||||||
|
{{
|
||||||
|
This object provides console I/O functions for SpinSim. It implements the same methods as FullDuplexSerial.
|
||||||
|
}}
|
||||||
|
con
|
||||||
|
SYS_COMMAND = $12340000
|
||||||
|
SYS_LOCKNUM = $12340002
|
||||||
|
SYS_PARM = $12340004
|
||||||
|
|
||||||
|
SYS_CON_PUTCH = 1
|
||||||
|
SYS_CON_GETCH = 2
|
||||||
|
|
||||||
|
PUB start(rxpin, txpin, mode, baudrate) : okay
|
||||||
|
ifnot word[SYS_LOCKNUM]
|
||||||
|
word[SYS_LOCKNUM] := locknew + 1
|
||||||
|
return 1
|
||||||
|
|
||||||
|
PUB stop
|
||||||
|
|
||||||
|
|
||||||
|
PUB rxflush
|
||||||
|
|
||||||
|
'' Flush receive buffer
|
||||||
|
|
||||||
|
repeat while rxcheck => 0
|
||||||
|
|
||||||
|
|
||||||
|
PUB rxtime(ms) : rxbyte | t
|
||||||
|
|
||||||
|
'' Wait ms milliseconds for a byte to be received
|
||||||
|
'' returns -1 if no byte received, $00..$FF if byte
|
||||||
|
|
||||||
|
t := cnt
|
||||||
|
repeat until (rxbyte := rxcheck) => 0 or (cnt - t) / (clkfreq / 1000) > ms
|
||||||
|
|
||||||
|
|
||||||
|
PUB rx : rxbyte
|
||||||
|
|
||||||
|
'' Receive byte (may wait for byte)
|
||||||
|
'' returns $00..$FF
|
||||||
|
|
||||||
|
repeat while (rxbyte := rxcheck) < 0
|
||||||
|
|
||||||
|
PUB rxcheck | locknum
|
||||||
|
locknum := word[SYS_LOCKNUM] - 1
|
||||||
|
if locknum == -1
|
||||||
|
return -1
|
||||||
|
repeat until not lockset(locknum)
|
||||||
|
word[SYS_COMMAND] := SYS_CON_GETCH
|
||||||
|
repeat while word[SYS_COMMAND]
|
||||||
|
result := long[SYS_PARM]
|
||||||
|
lockclr(locknum)
|
||||||
|
|
||||||
|
|
||||||
|
PUB tx(txbyte) | locknum
|
||||||
|
|
||||||
|
'' Send byte (may wait for room in buffer)
|
||||||
|
locknum := word[SYS_LOCKNUM] - 1
|
||||||
|
if locknum == -1
|
||||||
|
return
|
||||||
|
repeat until not lockset(locknum)
|
||||||
|
long[SYS_PARM] := txbyte
|
||||||
|
word[SYS_COMMAND] := SYS_CON_PUTCH
|
||||||
|
repeat while word[SYS_COMMAND]
|
||||||
|
lockclr(locknum)
|
||||||
|
|
||||||
|
|
||||||
|
PUB str(stringptr)
|
||||||
|
|
||||||
|
'' Send string
|
||||||
|
|
||||||
|
repeat strsize(stringptr)
|
||||||
|
tx(byte[stringptr++])
|
||||||
|
|
||||||
|
|
||||||
|
PUB dec(value) | i, x
|
||||||
|
|
||||||
|
'' Print a decimal number
|
||||||
|
|
||||||
|
x := value == NEGX 'Check for max negative
|
||||||
|
if value < 0
|
||||||
|
value := ||(value+x) 'If negative, make positive; adjust for max negative
|
||||||
|
tx("-") 'and output sign
|
||||||
|
|
||||||
|
i := 1_000_000_000 'Initialize divisor
|
||||||
|
|
||||||
|
repeat 10 'Loop for 10 digits
|
||||||
|
if value => i
|
||||||
|
tx(value / i + "0" + x*(i == 1)) 'If non-zero digit, output digit; adjust for max negative
|
||||||
|
value //= i 'and digit from value
|
||||||
|
result~~ 'flag non-zero found
|
||||||
|
elseif result or i == 1
|
||||||
|
tx("0") 'If zero digit (or only digit) output it
|
||||||
|
i /= 10 'Update divisor
|
||||||
|
|
||||||
|
PUB hex(value, digits)
|
||||||
|
|
||||||
|
'' Print a hexadecimal number
|
||||||
|
|
||||||
|
value <<= (8 - digits) << 2
|
||||||
|
repeat digits
|
||||||
|
tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
|
||||||
|
'tx(hexdigit[(value <-= 4) & $F])
|
||||||
|
|
||||||
|
PUB bin(value, digits)
|
||||||
|
|
||||||
|
'' Print a binary number
|
||||||
|
|
||||||
|
value <<= 32 - digits
|
||||||
|
repeat digits
|
||||||
|
tx((value <-= 1) & 1 + "0")
|
||||||
|
|
||||||
|
PUB out(char)
|
||||||
|
tx(char)
|
||||||
|
{{
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
}}
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifdef LINUX
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "conion.h"
|
||||||
|
|
||||||
|
#ifdef STD_CONSOLE_INPUT
|
||||||
|
void initialize_console_io()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore_console_io()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int kbhit(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char getch(void)
|
||||||
|
{
|
||||||
|
return getchar();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
static struct termios oldt;
|
||||||
|
static int oldf;
|
||||||
|
static int lastkey = EOF;
|
||||||
|
static int initialized = 0;
|
||||||
|
|
||||||
|
void initialize_console_io()
|
||||||
|
{
|
||||||
|
struct termios newt;
|
||||||
|
tcgetattr(STDIN_FILENO, &oldt);
|
||||||
|
newt = oldt;
|
||||||
|
newt.c_lflag &= ~(ICANON | ECHO);
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||||
|
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore_console_io()
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
{
|
||||||
|
initialized = 0;
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, oldf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int kbhit(void)
|
||||||
|
{
|
||||||
|
if (lastkey == EOF)
|
||||||
|
lastkey = getchar();
|
||||||
|
|
||||||
|
return (lastkey != EOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
char getch(void)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
while (!kbhit());
|
||||||
|
ch = lastkey;
|
||||||
|
lastkey = EOF;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef __CONION_H__
|
||||||
|
#define __CONION_H__
|
||||||
|
|
||||||
|
#undef STD_CONSOLE_INPUT
|
||||||
|
|
||||||
|
int kbhit(void);
|
||||||
|
char getch(void);
|
||||||
|
void initialize_console_io(void);
|
||||||
|
void restore_console_io(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,222 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.54
|
||||||
|
' Copyright (c) 2012
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#ifdef LINUX
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "conion.h"
|
||||||
|
#else
|
||||||
|
#include <conio.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#endif
|
||||||
|
#include "interp.h"
|
||||||
|
#include "spindebug.h"
|
||||||
|
#include "eeprom.h"
|
||||||
|
#include "spinsim.h"
|
||||||
|
|
||||||
|
extern int32_t loopcount;
|
||||||
|
extern int32_t printflag;
|
||||||
|
extern int32_t baudrate;
|
||||||
|
extern int32_t eeprom;
|
||||||
|
extern char *hubram;
|
||||||
|
extern int32_t printbreak;
|
||||||
|
extern PasmVarsT PasmVars[8];
|
||||||
|
|
||||||
|
void GetDebugString(char *ptr);
|
||||||
|
int32_t RunProp(int32_t maxloops);
|
||||||
|
|
||||||
|
void Help(void)
|
||||||
|
{
|
||||||
|
printf("Debug Commands\n");
|
||||||
|
printf("help - Print command list\n");
|
||||||
|
printf("exit - Exit spinsim\n");
|
||||||
|
printf("step - Run one cycle\n");
|
||||||
|
printf("stepx - Run next executed instruction\n");
|
||||||
|
printf("run - Run continuously\n");
|
||||||
|
printf("verbose # - Set verbosity level\n");
|
||||||
|
printf("reboot - Reboot the Prop\n");
|
||||||
|
printf("setbr cog addr - Set breakpoint for cog to addr\n");
|
||||||
|
printf("state cog - Dump cog state\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
char *SkipChar(char *str, int value)
|
||||||
|
{
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
if (*str != value) break;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpState(PasmVarsT *pasmvars)
|
||||||
|
{
|
||||||
|
printf("cflag = %d, zflag = %d, waitflag = %d\n",
|
||||||
|
pasmvars->cflag, pasmvars->zflag, pasmvars->waitflag);
|
||||||
|
printf("ptra = %5.5x, ptrb = %5.5x, ptrx = %2.2x, ptry = %2.2x, inda = %3.3x, indb = %3.3x\n",
|
||||||
|
pasmvars->ptra, pasmvars->ptra, pasmvars->ptrx,
|
||||||
|
pasmvars->ptry, pasmvars->inda, pasmvars->indb);
|
||||||
|
printf("pc1 = %8.8x, instruct1 = %8.8x\n", pasmvars->pc1, pasmvars->instruct1);
|
||||||
|
printf("pc2 = %8.8x, instruct2 = %8.8x\n", pasmvars->pc2, pasmvars->instruct2);
|
||||||
|
printf("pc3 = %8.8x, instruct3 = %8.8x\n", pasmvars->pc3, pasmvars->instruct3);
|
||||||
|
printf("pc4 = %8.8x, instruct4 = %8.8x\n", pasmvars->pc4, pasmvars->instruct4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug(void)
|
||||||
|
{
|
||||||
|
int runflag = 1;
|
||||||
|
char buffer[200];
|
||||||
|
char lastcmd[200];
|
||||||
|
int maxloops;
|
||||||
|
int stepflag = 0;
|
||||||
|
int saveprintflag = 0;
|
||||||
|
|
||||||
|
strcpy(lastcmd, "help");
|
||||||
|
while (runflag)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
printf("\nDEBUG> ");
|
||||||
|
fflush(stdout);
|
||||||
|
GetDebugString(buffer);
|
||||||
|
if (buffer[0] == 0) strcpy(buffer, lastcmd);
|
||||||
|
strcpy(lastcmd, buffer);
|
||||||
|
if (!strcmp(buffer, "exit"))
|
||||||
|
{
|
||||||
|
runflag = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!strcmp(buffer, "step"))
|
||||||
|
{
|
||||||
|
stepflag = 1;
|
||||||
|
saveprintflag = printflag;
|
||||||
|
printflag = 0xffffffff;
|
||||||
|
LONG(SYS_DEBUG) = printflag;
|
||||||
|
maxloops = loopcount + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!strcmp(buffer, "stepx"))
|
||||||
|
{
|
||||||
|
stepflag = 1;
|
||||||
|
saveprintflag = printflag;
|
||||||
|
printflag = 0x22222222;
|
||||||
|
LONG(SYS_DEBUG) = printflag;
|
||||||
|
printbreak = 1;
|
||||||
|
maxloops = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!strncmp(buffer, "verbose", 7))
|
||||||
|
{
|
||||||
|
char *ptr = SkipChar(buffer+7, ' ');
|
||||||
|
if (*ptr == 0)
|
||||||
|
printflag = 0xffffffff;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sscanf(ptr, "%x", &printflag);
|
||||||
|
if (ptr[1] == 0)
|
||||||
|
printflag *= 0x11111111;
|
||||||
|
}
|
||||||
|
LONG(SYS_DEBUG) = printflag;
|
||||||
|
}
|
||||||
|
else if (!strcmp(buffer, "help"))
|
||||||
|
{
|
||||||
|
Help();
|
||||||
|
}
|
||||||
|
else if (!strcmp(buffer, "run"))
|
||||||
|
{
|
||||||
|
maxloops = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!strncmp(buffer, "setbr ", 6))
|
||||||
|
{
|
||||||
|
int cognum, address;
|
||||||
|
sscanf(buffer+6, "%x %x", &cognum, &address);
|
||||||
|
PasmVars[cognum&7].breakpnt = address;
|
||||||
|
LONG(SYS_DEBUG) = printflag;
|
||||||
|
}
|
||||||
|
else if (!strcmp(buffer, "reboot"))
|
||||||
|
{
|
||||||
|
RebootProp();
|
||||||
|
}
|
||||||
|
else if (!strncmp(buffer, "state ", 6))
|
||||||
|
{
|
||||||
|
int cognum = buffer[6] & 7;
|
||||||
|
DumpState(&PasmVars[cognum]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("?\n");
|
||||||
|
}
|
||||||
|
if (runflag) RunProp(maxloops);
|
||||||
|
if (stepflag)
|
||||||
|
{
|
||||||
|
stepflag = 0;
|
||||||
|
printbreak = 0;
|
||||||
|
printflag = saveprintflag;
|
||||||
|
LONG(SYS_DEBUG) = printflag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetDebugString(char *ptr)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
#ifndef STD_CONSOLE_INPUT
|
||||||
|
while (!kbhit());
|
||||||
|
#endif
|
||||||
|
value = getch();
|
||||||
|
putchx(value);
|
||||||
|
if (value == 13 || value == 10)
|
||||||
|
{
|
||||||
|
*ptr = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*ptr++ = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t RunProp(int32_t maxloops)
|
||||||
|
{
|
||||||
|
int32_t runflag = 1;
|
||||||
|
|
||||||
|
while (runflag && (maxloops < 0 || loopcount < maxloops))
|
||||||
|
{
|
||||||
|
runflag = step_chip();
|
||||||
|
CheckCommand();
|
||||||
|
if (baudrate)
|
||||||
|
{
|
||||||
|
CheckSerialOut();
|
||||||
|
if (CheckSerialIn()) return 1;
|
||||||
|
}
|
||||||
|
if (eeprom)
|
||||||
|
CheckEEProm();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,223 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.54
|
||||||
|
' Copyright (c) 2012
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "spinsim.h"
|
||||||
|
|
||||||
|
extern int32_t pin_val;
|
||||||
|
extern int32_t eeprom;
|
||||||
|
|
||||||
|
static int32_t scl_prev = 1;
|
||||||
|
static int32_t sda_prev = 1;
|
||||||
|
static int32_t state = 0;
|
||||||
|
static int32_t count = 0;
|
||||||
|
static int32_t value = 0;
|
||||||
|
static int32_t control = 0;
|
||||||
|
static int32_t address = 0;
|
||||||
|
static int32_t drivepin = 0;
|
||||||
|
static int32_t driveval = 0;
|
||||||
|
|
||||||
|
static unsigned char memory[256*256];
|
||||||
|
|
||||||
|
void CheckEEProm()
|
||||||
|
{
|
||||||
|
int32_t scl = (pin_val >> 28) & 1;
|
||||||
|
int32_t sda = (pin_val >> 29) & 1;
|
||||||
|
|
||||||
|
if (!eeprom) return;
|
||||||
|
|
||||||
|
//printf("scl = %d, sda = %d\n", scl, sda);
|
||||||
|
|
||||||
|
if (!drivepin && scl_prev && sda_prev && scl && !sda)
|
||||||
|
{
|
||||||
|
//printf("Start\n");
|
||||||
|
count = 0;
|
||||||
|
state = 1;
|
||||||
|
control = 0;
|
||||||
|
drivepin = 0;
|
||||||
|
}
|
||||||
|
else if (!drivepin && scl_prev && !sda_prev && scl && sda)
|
||||||
|
{
|
||||||
|
//printf("Stop\n");
|
||||||
|
state = 0;
|
||||||
|
drivepin = 0;
|
||||||
|
}
|
||||||
|
else if (state && scl_prev && !scl)
|
||||||
|
{
|
||||||
|
drivepin = 0;
|
||||||
|
if (state == 1)
|
||||||
|
{
|
||||||
|
if (count) control = (control << 1) | sda_prev;
|
||||||
|
count++;
|
||||||
|
if (count == 9)
|
||||||
|
{
|
||||||
|
//printf("control = %2.2x\n", control);
|
||||||
|
if ((control & 0xf0) == 0xa0)
|
||||||
|
{
|
||||||
|
drivepin = 1;
|
||||||
|
driveval = 0;
|
||||||
|
count = 0;
|
||||||
|
if (control & 1)
|
||||||
|
state = 5;
|
||||||
|
else
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == 2 || state == 3)
|
||||||
|
{
|
||||||
|
if (count) address = (address << 1) | sda_prev;
|
||||||
|
else if (state == 2) address = 0;
|
||||||
|
count++;
|
||||||
|
if (count == 9)
|
||||||
|
{
|
||||||
|
//if (state == 3) printf("address = %2.2x\n", address);
|
||||||
|
state++;
|
||||||
|
drivepin = 1;
|
||||||
|
driveval = 0;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == 4)
|
||||||
|
{
|
||||||
|
if (count) value = (value << 1) | sda_prev;
|
||||||
|
count++;
|
||||||
|
if (count == 9)
|
||||||
|
{
|
||||||
|
//printf("value = %2.2x\n", value);
|
||||||
|
memory[address] = value;
|
||||||
|
address = (address + 1) & 0xffff;
|
||||||
|
drivepin = 1;
|
||||||
|
driveval = 0;
|
||||||
|
count = 0;
|
||||||
|
eeprom = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == 5)
|
||||||
|
{
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
if (sda_prev)
|
||||||
|
state = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = memory[address];
|
||||||
|
drivepin = 1;
|
||||||
|
driveval = (value >> 7) & 1;
|
||||||
|
value <<= 1;
|
||||||
|
count++;
|
||||||
|
address = (address + 1) & 0xffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (count < 8)
|
||||||
|
{
|
||||||
|
drivepin = 1;
|
||||||
|
driveval = (value >> 7) & 1;
|
||||||
|
value <<= 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
drivepin = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (drivepin)
|
||||||
|
{
|
||||||
|
pin_val = (pin_val & (~(1 << 29))) | (driveval << 29);
|
||||||
|
sda = driveval;
|
||||||
|
}
|
||||||
|
scl_prev = scl;
|
||||||
|
sda_prev = sda;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE *OpenFile(char *fname, char *mode)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(fname, mode);
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
printf("Could not open %s\n", fname);
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEPromInit(char *fname)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
if (!eeprom) return;
|
||||||
|
|
||||||
|
//printf("EEPromInit(%s)\n", fname);
|
||||||
|
|
||||||
|
if (fname)
|
||||||
|
{
|
||||||
|
file = fopen("eeprom.dat", "r");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
fread(memory, 1, 65536, file);
|
||||||
|
fclose(file);
|
||||||
|
memset(memory, 0, 32768);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memset(memory, 0, 65536);
|
||||||
|
file = OpenFile(fname, "r");
|
||||||
|
fread(memory, 1, 65536, file);
|
||||||
|
fclose(file);
|
||||||
|
file = OpenFile("eeprom.dat", "w");
|
||||||
|
fwrite(memory, 1, 65536, file);
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file = OpenFile("eeprom.dat", "r");
|
||||||
|
fread(memory, 1, 65536, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEPromClose(void)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
if (eeprom == 2)
|
||||||
|
{
|
||||||
|
file = OpenFile("eeprom.dat", "w");
|
||||||
|
fwrite(memory, 1, 65536, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEPromCopy(char *mem)
|
||||||
|
{
|
||||||
|
if (!eeprom) return;
|
||||||
|
|
||||||
|
//printf("EEPromCopy\n");
|
||||||
|
memcpy(mem, memory, 32768);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,4 @@
|
||||||
|
void CheckEEProm(void);
|
||||||
|
void EEPromInit(char *fname);
|
||||||
|
void EEPromCopy(char *mem);
|
||||||
|
void EEPromClose(void);
|
|
@ -0,0 +1,189 @@
|
||||||
|
'******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 1.0
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************
|
||||||
|
{{
|
||||||
|
This object provide file I/O functions for SpinSim. It currently implements only popen, pclose and pread.
|
||||||
|
The methods a similar to the ones the FSRW object. A dummy mount routine is provide for compatibility.
|
||||||
|
}}
|
||||||
|
con
|
||||||
|
SYS_COMMAND = $12340000
|
||||||
|
SYS_LOCKNUM = $12340002
|
||||||
|
SYS_PARM = $12340004
|
||||||
|
|
||||||
|
SYS_FILE_OPEN = 3
|
||||||
|
SYS_FILE_CLOSE = 4
|
||||||
|
SYS_FILE_READ = 5
|
||||||
|
SYS_FILE_WRITE = 6
|
||||||
|
SYS_FILE_OPENDIR = 7
|
||||||
|
SYS_FILE_CLOSEDIR = 8
|
||||||
|
SYS_FILE_READDIR = 9
|
||||||
|
SYS_FILE_SEEK = 10
|
||||||
|
SYS_FILE_TELL = 11
|
||||||
|
SYS_FILE_REMOVE = 12
|
||||||
|
SYS_FILE_CHDIR = 13
|
||||||
|
SYS_FILE_GETCWD = 14
|
||||||
|
SYS_FILE_MKDIR = 15
|
||||||
|
SYS_FILE_GETMOD = 16
|
||||||
|
|
||||||
|
dat
|
||||||
|
handle0 long 0
|
||||||
|
dirhand0 long 0
|
||||||
|
direntbuf long 0[20]
|
||||||
|
|
||||||
|
'****************************
|
||||||
|
' FSRW Routines
|
||||||
|
'****************************
|
||||||
|
pub mount(pin)
|
||||||
|
ifnot word[SYS_LOCKNUM]
|
||||||
|
word[SYS_LOCKNUM] := locknew + 1
|
||||||
|
|
||||||
|
pub mount_explicit(DO, CLK, DI, CS)
|
||||||
|
ifnot word[SYS_LOCKNUM]
|
||||||
|
word[SYS_LOCKNUM] := locknew + 1
|
||||||
|
|
||||||
|
pub popen(fname, mode)
|
||||||
|
pclose
|
||||||
|
handle0 := hopen(fname, mode)
|
||||||
|
ifnot handle0
|
||||||
|
return -1
|
||||||
|
|
||||||
|
pub pclose
|
||||||
|
if handle0
|
||||||
|
hclose(handle0)
|
||||||
|
handle0~
|
||||||
|
|
||||||
|
pub pread(buffer, num)
|
||||||
|
return hread(handle0, buffer, num)
|
||||||
|
|
||||||
|
pub pwrite(buffer, num)
|
||||||
|
return hwrite(handle0, buffer, num)
|
||||||
|
|
||||||
|
pub opendir
|
||||||
|
if dirhand0
|
||||||
|
hclosedir(dirhand0)
|
||||||
|
dirhand0 := hopendir
|
||||||
|
ifnot dirhand0
|
||||||
|
return -1
|
||||||
|
|
||||||
|
pub nextfile(fbuf)
|
||||||
|
return hnextfile(dirhand0, fbuf)
|
||||||
|
|
||||||
|
pub seek(position)
|
||||||
|
result := hseek(handle0, position)
|
||||||
|
|
||||||
|
pub tell
|
||||||
|
result := htell(handle0)
|
||||||
|
|
||||||
|
pub get_filesize
|
||||||
|
result := hget_filesize(handle0)
|
||||||
|
|
||||||
|
'****************************
|
||||||
|
' handle Routines
|
||||||
|
'****************************
|
||||||
|
pub hopen(fname, mode)
|
||||||
|
if mode => "a" and mode =< "z"
|
||||||
|
mode -= "a" - "A"
|
||||||
|
if mode == "R"
|
||||||
|
mode := string("rb")
|
||||||
|
elseif mode == "W"
|
||||||
|
mode := string("wb")
|
||||||
|
elseif mode == "A"
|
||||||
|
mode := string("ab")
|
||||||
|
elseif mode == "D"
|
||||||
|
return SystemCall(SYS_FILE_REMOVE, fname)
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
result := SystemCall(SYS_FILE_OPEN, @fname)
|
||||||
|
|
||||||
|
pub hclose(handle)
|
||||||
|
result := SystemCall(SYS_FILE_CLOSE, handle)
|
||||||
|
|
||||||
|
pub hread(handle, buffer, num)
|
||||||
|
result := SystemCall(SYS_FILE_READ, @handle)
|
||||||
|
|
||||||
|
pub hwrite(handle, buffer, num)
|
||||||
|
result := SystemCall(SYS_FILE_WRITE, @handle)
|
||||||
|
|
||||||
|
pub hopendir
|
||||||
|
result := SystemCall(SYS_FILE_OPENDIR, 0)
|
||||||
|
|
||||||
|
pub hclosedir(handle)
|
||||||
|
result := SystemCall(SYS_FILE_CLOSEDIR, handle)
|
||||||
|
|
||||||
|
pub hnextfile(handle, fbuf) | num
|
||||||
|
result := hreaddir(handle)
|
||||||
|
if result
|
||||||
|
num := strsize(@direntbuf[2])
|
||||||
|
if num > 31
|
||||||
|
num := 31
|
||||||
|
bytemove(fbuf, @direntbuf[2], num)
|
||||||
|
byte[fbuf][num] := 0
|
||||||
|
|
||||||
|
pub hreaddir(handle) | pdirent
|
||||||
|
pdirent := @direntbuf
|
||||||
|
result := SystemCall(SYS_FILE_READDIR, @handle)
|
||||||
|
if result
|
||||||
|
result := @direntbuf
|
||||||
|
|
||||||
|
pub hseek(handle, position) | whence
|
||||||
|
whence~
|
||||||
|
result := SystemCall(SYS_FILE_SEEK, @handle)
|
||||||
|
|
||||||
|
pub htell(handle)
|
||||||
|
result := SystemCall(SYS_FILE_TELL, handle)
|
||||||
|
|
||||||
|
pub hget_filesize(handle) | offset, whence, position, filesize
|
||||||
|
position := SystemCall(SYS_FILE_TELL, handle)
|
||||||
|
offset~
|
||||||
|
whence := 2
|
||||||
|
SystemCall(SYS_FILE_SEEK, @handle)
|
||||||
|
filesize := SystemCall(SYS_FILE_TELL, handle)
|
||||||
|
offset := position
|
||||||
|
whence~
|
||||||
|
SystemCall(SYS_FILE_SEEK, @handle)
|
||||||
|
return filesize
|
||||||
|
|
||||||
|
pub chdir(path)
|
||||||
|
result := SystemCall(SYS_FILE_CHDIR, path)
|
||||||
|
|
||||||
|
pub getcwd(str, num)
|
||||||
|
result := SystemCall(SYS_FILE_CHDIR, @str)
|
||||||
|
|
||||||
|
pub mkdir(path)
|
||||||
|
result := SystemCall(SYS_FILE_MKDIR, path)
|
||||||
|
|
||||||
|
pub getmod(fname)
|
||||||
|
result := SystemCall(SYS_FILE_GETMOD, fname)
|
||||||
|
|
||||||
|
pub SystemCall(command, parm) | locknum
|
||||||
|
locknum := word[SYS_LOCKNUM] - 1
|
||||||
|
if locknum == -1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
repeat until not lockset(locknum)
|
||||||
|
long[SYS_PARM] := parm
|
||||||
|
word[SYS_COMMAND] := command
|
||||||
|
repeat while word[SYS_COMMAND]
|
||||||
|
result := long[SYS_PARM]
|
||||||
|
lockclr(locknum)
|
||||||
|
{{
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
}}
|
||||||
|
|
|
@ -0,0 +1,418 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Version 0.54
|
||||||
|
' Copyright (c) 2010, 2011, 2012
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#ifdef LINUX
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "conion.h"
|
||||||
|
#else
|
||||||
|
#include <conio.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#endif
|
||||||
|
#include "interp.h"
|
||||||
|
#include "spinsim.h"
|
||||||
|
|
||||||
|
#define GCC_REG_BASE 0
|
||||||
|
|
||||||
|
extern FILE *logfile;
|
||||||
|
extern FILE *tracefile;
|
||||||
|
extern FILE *cmdfile;
|
||||||
|
extern PasmVarsT PasmVars[8];
|
||||||
|
extern char *hubram;
|
||||||
|
char cmd[1028];
|
||||||
|
extern int32_t proptwo;
|
||||||
|
extern int32_t profile;
|
||||||
|
extern int32_t loopcount;
|
||||||
|
|
||||||
|
void reply(char *ptr, int len){
|
||||||
|
unsigned char cksum = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
putc('$', stdout);
|
||||||
|
if(logfile) fprintf(logfile, "sim>$");
|
||||||
|
for(i = 0; i < len; i++){
|
||||||
|
putc(ptr[i], stdout);
|
||||||
|
if(logfile) putc(ptr[i], logfile);
|
||||||
|
cksum += ptr[i];
|
||||||
|
}
|
||||||
|
fprintf(stdout, "#%02x", cksum);
|
||||||
|
if(logfile) fprintf(logfile, "#%02x", cksum);
|
||||||
|
if(logfile) putc('\n', logfile);
|
||||||
|
fflush(stdout);
|
||||||
|
if(logfile) fflush(logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
char parse_byte(char *ch){
|
||||||
|
char s[3];
|
||||||
|
char val;
|
||||||
|
s[0] = ch[0];
|
||||||
|
s[1] = ch[1];
|
||||||
|
s[2] = 0;
|
||||||
|
val = 0xff & strtol(s, NULL, 16);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_byte(uint32_t addr){
|
||||||
|
if(addr & 0x80000000){
|
||||||
|
int cog = (addr >> 28) - 8;
|
||||||
|
uint32_t tmp;
|
||||||
|
tmp = PasmVars[cog].mem[(addr & 0x000007ff) >> 2];
|
||||||
|
return (tmp >> 8*(addr & 0x3)) & 0xff;
|
||||||
|
} else {
|
||||||
|
return BYTE(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void put_byte(uint32_t addr, unsigned char val){
|
||||||
|
if(addr & 0x80000000){
|
||||||
|
int cog = (addr >> 28) - 8;
|
||||||
|
uint32_t tmp;
|
||||||
|
tmp = PasmVars[cog].mem[(addr & 0x000007ff) >> 2];
|
||||||
|
switch(addr & 3){
|
||||||
|
case 0:
|
||||||
|
tmp &= 0xffffff00;
|
||||||
|
tmp |= val;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tmp &= 0xffff00ff;
|
||||||
|
tmp |= val << 8;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tmp &= 0xff00ffff;
|
||||||
|
tmp |= val << 16;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
tmp &= 0x00ffffff;
|
||||||
|
tmp |= val << 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PasmVars[cog].mem[(addr & 0x000007ff) >> 2] = tmp;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
BYTE(addr) = val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_cmd(){
|
||||||
|
int i = 0;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
do{
|
||||||
|
ch = getc(cmdfile);
|
||||||
|
} while(ch != '$');
|
||||||
|
|
||||||
|
if(logfile) fprintf(logfile, "gdb>");
|
||||||
|
if(logfile) putc(ch, logfile);
|
||||||
|
|
||||||
|
for(i = 0; i < sizeof(cmd); i++){
|
||||||
|
ch = getc(cmdfile);
|
||||||
|
if(logfile) putc(ch, logfile);
|
||||||
|
if(ch == '#') break;
|
||||||
|
cmd[i] = ch;
|
||||||
|
}
|
||||||
|
cmd[i] = 0;
|
||||||
|
// eat the checksum
|
||||||
|
ch = getc(cmdfile);
|
||||||
|
if(logfile) putc(ch, logfile);
|
||||||
|
ch = getc(cmdfile);
|
||||||
|
if(logfile) putc(ch, logfile);
|
||||||
|
if(logfile) putc('\n', logfile);
|
||||||
|
// send an ACK
|
||||||
|
putchar('+');
|
||||||
|
fflush(stdout);
|
||||||
|
if(logfile) fflush(logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tohex(char x){
|
||||||
|
if(x >= '0' && x <= '9') return x - '0';
|
||||||
|
if(x >= 'a' && x <= 'f') return 10 + x - 'a';
|
||||||
|
if(x >= 'A' && x <= 'F') return 10 + x - 'A';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t get_addr(int *i){
|
||||||
|
int32_t reg;
|
||||||
|
reg = tohex(cmd[(*i)++]) << 4;
|
||||||
|
reg |= tohex(cmd[(*i)++]) << 0;
|
||||||
|
reg |= tohex(cmd[(*i)++]) << 12;
|
||||||
|
reg |= tohex(cmd[(*i)++]) << 8;
|
||||||
|
reg |= tohex(cmd[(*i)++]) << 20;
|
||||||
|
reg |= tohex(cmd[(*i)++]) << 16;
|
||||||
|
reg |= tohex(cmd[(*i)++]) << 28;
|
||||||
|
reg |= tohex(cmd[(*i)++]) << 24;
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bkpt {
|
||||||
|
struct bkpt *next;
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bkpt *bkpt = 0;
|
||||||
|
|
||||||
|
// Check the cog's PC to see if the LMM microcode is at an appropriate place
|
||||||
|
// for a breakpoint to occur. We don't want to break on LMM administrative
|
||||||
|
// instructions.
|
||||||
|
// FIXME we need a more general way to do this. This is too dependent on special knowledge.
|
||||||
|
int breakable_point(int i){
|
||||||
|
int32_t pc = PasmVars[i].pc;
|
||||||
|
if ((pc == 0x0000004c/4)
|
||||||
|
|| (pc == 0x00000058/4)
|
||||||
|
|| (pc == 0x00000064/4)
|
||||||
|
|| (pc == 0x00000070/4)
|
||||||
|
|| (pc == 0x0000007c/4)
|
||||||
|
|| (pc == 0x00000088/4)
|
||||||
|
|| (pc == 0x00000094/4)
|
||||||
|
|| (pc == 0x000000a0/4))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdb(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
char response[1024];
|
||||||
|
unsigned int addr;
|
||||||
|
int len;
|
||||||
|
char *end;
|
||||||
|
char val;
|
||||||
|
int32_t reg;
|
||||||
|
int cog = 0;
|
||||||
|
char *halt_code = "S05";
|
||||||
|
|
||||||
|
if(logfile) fprintf(logfile, "\n\nStarting log:\n");
|
||||||
|
|
||||||
|
RebootProp();
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
get_cmd();
|
||||||
|
i = 0;
|
||||||
|
switch(cmd[i++]){
|
||||||
|
case 'g':
|
||||||
|
for(i = 0; i < 18; i++){
|
||||||
|
reg = PasmVars[cog].mem[GCC_REG_BASE + i];
|
||||||
|
sprintf(response+8*i,
|
||||||
|
"%02x%02x%02x%02x",
|
||||||
|
(unsigned char)(reg & 0xff),
|
||||||
|
(unsigned char)((reg>>8) & 0xff),
|
||||||
|
(unsigned char)((reg>>16) & 0xff),
|
||||||
|
(unsigned char)((reg>>24) & 0xff));
|
||||||
|
}
|
||||||
|
reg = PasmVars[cog].pc * 4 + 0x80000000 + cog * 0x10000000;
|
||||||
|
sprintf(response+8*i,
|
||||||
|
"%02x%02x%02x%02x",
|
||||||
|
(unsigned char)(reg & 0xff),
|
||||||
|
(unsigned char)((reg>>8) & 0xff),
|
||||||
|
(unsigned char)((reg>>16) & 0xff),
|
||||||
|
(unsigned char)((reg>>24) & 0xff));
|
||||||
|
reply(response, 8*18+8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'G':
|
||||||
|
for(j = 0; j < 18; j++){
|
||||||
|
PasmVars[cog].mem[GCC_REG_BASE + j] = get_addr(&i);
|
||||||
|
}
|
||||||
|
// Ignore writes to cog pc. Instead, reset it to be
|
||||||
|
// ready for a fresh instruction.
|
||||||
|
// This is too magical. How do we fix it?
|
||||||
|
PasmVars[cog].pc = 0x12;
|
||||||
|
reply("OK",2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
addr = strtol(&cmd[i], &end, 16);
|
||||||
|
i = (size_t)end - (size_t)cmd;
|
||||||
|
i++;
|
||||||
|
len = strtol(&cmd[i], NULL, 16);
|
||||||
|
if(len > 512) len = 512;
|
||||||
|
j = 0;
|
||||||
|
while(len--){
|
||||||
|
val = get_byte(addr);
|
||||||
|
addr++;
|
||||||
|
sprintf(&response[j], "%02x", (unsigned char)val);
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
reply(response, j);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'M':
|
||||||
|
addr = strtol(&cmd[i], &end, 16);
|
||||||
|
i = (size_t)end - (size_t)cmd;
|
||||||
|
i++;
|
||||||
|
len = strtol(&cmd[i], &end, 16);
|
||||||
|
i = (size_t)end - (size_t)cmd;
|
||||||
|
i++;
|
||||||
|
while(len--){
|
||||||
|
val = parse_byte(&cmd[i]);
|
||||||
|
i += 2;
|
||||||
|
put_byte(addr, val & 0xff);
|
||||||
|
addr++;
|
||||||
|
}
|
||||||
|
reply("OK",2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
if(cmd[i]){
|
||||||
|
// Get the new LMM PC, reset the microcode
|
||||||
|
PasmVars[cog].mem[GCC_REG_BASE + 17] = get_addr(&i);
|
||||||
|
PasmVars[cog].pc = 0x12;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int brk = 0;
|
||||||
|
do {
|
||||||
|
int i;
|
||||||
|
// Step through a full LMM instruction
|
||||||
|
step_chip();
|
||||||
|
for(i = 0; i < 8; i++){
|
||||||
|
if(breakable_point(i)) brk = 1;
|
||||||
|
}
|
||||||
|
} while (!brk);
|
||||||
|
}
|
||||||
|
halt_code = "S05";
|
||||||
|
reply(halt_code, 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
if(cmd[i]){
|
||||||
|
PasmVars[cog].mem[GCC_REG_BASE + 17] = get_addr(&i);
|
||||||
|
PasmVars[cog].pc = 0x12;
|
||||||
|
}
|
||||||
|
halt_code = "S02";
|
||||||
|
do {
|
||||||
|
int brk = 0;
|
||||||
|
struct bkpt *b;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if(breakable_point(i)){
|
||||||
|
// Look to see if the cog's LMM PC is at a breakpoint
|
||||||
|
for(b = (struct bkpt *)&bkpt; b->next; b = b->next){
|
||||||
|
if((PasmVars[i].mem[GCC_REG_BASE + 17] >= b->next->addr)
|
||||||
|
&& (PasmVars[i].mem[GCC_REG_BASE + 17] <= b->next->addr + b->next->len)){
|
||||||
|
brk = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(brk){
|
||||||
|
halt_code = "S05";
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
step_chip();
|
||||||
|
}
|
||||||
|
} while(getch() != 0x03); // look for a CTRL-C
|
||||||
|
reply(halt_code, 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'H':
|
||||||
|
if((cmd[i] == 'g') && (cmd[i+1] == '0')){
|
||||||
|
reply("OK", 2);
|
||||||
|
} else {
|
||||||
|
reply("", 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'k':
|
||||||
|
reply("OK", 2);
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
case 'z':
|
||||||
|
/* Remove breakpoint */
|
||||||
|
if(cmd[i++] == '0'){
|
||||||
|
long addr;
|
||||||
|
long len;
|
||||||
|
struct bkpt *b;
|
||||||
|
char *p = &cmd[i];
|
||||||
|
|
||||||
|
p++; /* Skip the comma */
|
||||||
|
addr = strtol(p, &p, 16);
|
||||||
|
p++; /* Skip the other comma */
|
||||||
|
len = strtol(p, NULL, 16);
|
||||||
|
for(b = (struct bkpt *)&bkpt; b && b->next; b = b->next){
|
||||||
|
if((b->next->addr == addr) && (b->next->len == len)){
|
||||||
|
struct bkpt *t = b->next;
|
||||||
|
b->next = t->next;
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply("OK", 2);
|
||||||
|
} else {
|
||||||
|
reply("", 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Z':
|
||||||
|
/* Set breakpoint */
|
||||||
|
if(cmd[i++] == '0'){
|
||||||
|
long addr;
|
||||||
|
long len;
|
||||||
|
struct bkpt *b;
|
||||||
|
char *p = &cmd[i];
|
||||||
|
p++; /* Skip the comma */
|
||||||
|
addr = strtol(p, &p, 16);
|
||||||
|
p++; /* Skip the other comma */
|
||||||
|
len = strtol(p, NULL, 16);
|
||||||
|
for(b = (struct bkpt *)&bkpt; b->next; b = b->next){
|
||||||
|
if((b->addr == addr) && (b->len == len)){
|
||||||
|
/* Duplicate; bail out */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(b->next){
|
||||||
|
/* Was a duplicate, do nothing */
|
||||||
|
} else {
|
||||||
|
struct bkpt *t = (struct bkpt *)malloc(sizeof(struct bkpt));
|
||||||
|
if(!t){
|
||||||
|
fprintf(stderr, "Failed to allocate a breakpoint structure\n");
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
t->addr = addr;
|
||||||
|
t->len = len;
|
||||||
|
t->next = bkpt;
|
||||||
|
bkpt = t;
|
||||||
|
}
|
||||||
|
reply("OK", 2);
|
||||||
|
} else {
|
||||||
|
reply("", 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
reply(halt_code, 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
reply("", 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.21
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
//#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define BYTE(addr) (((uint8_t *)hubram)[MAP_ADDR(addr)])
|
||||||
|
#define WORD(addr) (((uint16_t *)hubram)[MAP_ADDR(addr) >> 1])
|
||||||
|
#define LONG(addr) (((int32_t *)hubram)[MAP_ADDR(addr) >> 2])
|
||||||
|
|
||||||
|
// Define system I/O addresses and commands
|
||||||
|
#define SYS_COMMAND 0x12340000
|
||||||
|
#define SYS_LOCKNUM 0x12340002
|
||||||
|
#define SYS_PARM 0x12340004
|
||||||
|
#define SYS_DEBUG 0x12340008
|
||||||
|
|
||||||
|
#define INVALIDATE_INSTR 0x80000000
|
||||||
|
|
||||||
|
// This struct is used by the PASM simulator
|
||||||
|
typedef struct PasmVarsS {
|
||||||
|
int32_t mem[512];
|
||||||
|
int32_t state;
|
||||||
|
int32_t pc;
|
||||||
|
int32_t cflag;
|
||||||
|
int32_t zflag;
|
||||||
|
int32_t cogid;
|
||||||
|
int32_t waitflag;
|
||||||
|
int32_t waitmode;
|
||||||
|
int32_t breakpnt;
|
||||||
|
// P2 variables
|
||||||
|
int32_t instruct1;
|
||||||
|
int32_t instruct2;
|
||||||
|
int32_t instruct3;
|
||||||
|
int32_t instruct4;
|
||||||
|
int32_t pc1;
|
||||||
|
int32_t pc2;
|
||||||
|
int32_t pc3;
|
||||||
|
int32_t pc4;
|
||||||
|
int32_t dcachehubaddr;
|
||||||
|
int32_t dcachecogaddr;
|
||||||
|
int32_t icachehubaddr[4];
|
||||||
|
int32_t icachenotused[4];
|
||||||
|
int32_t ptra;
|
||||||
|
int32_t ptra0;
|
||||||
|
int32_t ptrb;
|
||||||
|
int32_t ptrb0;
|
||||||
|
int32_t ptrx;
|
||||||
|
int32_t ptry;
|
||||||
|
int32_t inda;
|
||||||
|
int32_t inda0;
|
||||||
|
int32_t indabot;
|
||||||
|
int32_t indatop;
|
||||||
|
int32_t indb;
|
||||||
|
int32_t indb0;
|
||||||
|
int32_t indbbot;
|
||||||
|
int32_t indbtop;
|
||||||
|
int32_t repcnt;
|
||||||
|
int32_t repbot;
|
||||||
|
int32_t reptop;
|
||||||
|
int32_t repforever;
|
||||||
|
int32_t dcache[8];
|
||||||
|
int32_t icache[4][8];
|
||||||
|
int32_t retstack[4];
|
||||||
|
int32_t auxram[256];
|
||||||
|
int32_t printflag;
|
||||||
|
int32_t retptr;
|
||||||
|
int32_t divq;
|
||||||
|
int32_t divr;
|
||||||
|
int32_t divisor;
|
||||||
|
int32_t mulcount;
|
||||||
|
int32_t augsvalue;
|
||||||
|
int32_t augsflag;
|
||||||
|
int32_t augdvalue;
|
||||||
|
int32_t augdflag;
|
||||||
|
int32_t prefetch;
|
||||||
|
int32_t sqrt;
|
||||||
|
int32_t lastd;
|
||||||
|
int64_t acca;
|
||||||
|
int64_t accb;
|
||||||
|
int64_t mul;
|
||||||
|
} PasmVarsT;
|
||||||
|
|
||||||
|
// This struct is used by the Spin simulator
|
||||||
|
// It is a subset of PasmVarsT starting at mem[0x1e0]
|
||||||
|
typedef struct SpinVarsS {
|
||||||
|
int32_t x1e0; // $1e0
|
||||||
|
int32_t x1e1; // $1e1
|
||||||
|
int32_t x1e2; // $1e2
|
||||||
|
int32_t x1e3; // $1e3
|
||||||
|
int32_t x1e4; // $1e4
|
||||||
|
int32_t masklong; // $1e5
|
||||||
|
int32_t masktop; // $1e6
|
||||||
|
int32_t maskwr; // $1e7
|
||||||
|
int32_t lsb; // $1e8
|
||||||
|
int32_t id; // $1e9
|
||||||
|
int32_t dcall; // $1ea
|
||||||
|
int32_t pbase; // $1eb
|
||||||
|
int32_t vbase; // $1ec
|
||||||
|
int32_t dbase; // $1ed
|
||||||
|
int32_t pcurr; // $1ee
|
||||||
|
int32_t dcurr; // $1ef
|
||||||
|
int32_t par; // $1f0
|
||||||
|
int32_t cnt; // $1f1
|
||||||
|
int32_t ina; // $1f2
|
||||||
|
int32_t inb; // $1f3
|
||||||
|
int32_t outa; // $1f4
|
||||||
|
int32_t outb; // $1f5
|
||||||
|
int32_t dira; // $1f6
|
||||||
|
int32_t dirb; // $1f7
|
||||||
|
int32_t ctra; // $1f8
|
||||||
|
int32_t ctrb; // $1f9
|
||||||
|
int32_t frqa; // $1fa
|
||||||
|
int32_t frqb; // $1fb
|
||||||
|
int32_t phsa; // $1fc
|
||||||
|
int32_t phsb; // $1fd
|
||||||
|
int32_t vcfg; // $1fe
|
||||||
|
int32_t vscl; // $1ff
|
||||||
|
int32_t state;
|
||||||
|
} SpinVarsT;
|
||||||
|
|
||||||
|
void RebootProp(void);
|
||||||
|
int32_t GetCnt(void);
|
||||||
|
void UpdatePins(void);
|
||||||
|
int32_t MAP_ADDR(int32_t addr);
|
||||||
|
void DebugPasmInstruction(PasmVarsT *pasmvars);
|
||||||
|
int ExecutePasmInstruction(PasmVarsT *pasmvars);
|
||||||
|
void DebugPasmInstruction2(PasmVarsT *pasmvars);
|
||||||
|
int ExecutePasmInstruction2(PasmVarsT *pasmvars);
|
||||||
|
void StartCog(SpinVarsT *spinvars, int par, int cogid);
|
||||||
|
void StartPasmCog(PasmVarsT *pasmvars, int par, int addr, int cogid);
|
||||||
|
void StartPasmCog2(PasmVarsT *pasmvars, int par, int addr, int cogid);
|
||||||
|
/*
|
||||||
|
+ -----------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,250 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.21
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
typedef struct OpCodeS {
|
||||||
|
unsigned char opform;
|
||||||
|
unsigned char opcode;
|
||||||
|
char *opname;
|
||||||
|
} OpCodeT;
|
||||||
|
|
||||||
|
static OpCodeT optable[] = {
|
||||||
|
{0x00, 0x00, "ldfrmr"},
|
||||||
|
{0x00, 0x01, "ldfrm"},
|
||||||
|
{0x00, 0x02, "ldfrmar"},
|
||||||
|
{0x00, 0x03, "ldfrma"},
|
||||||
|
{0x05, 0x04, "jmp"},
|
||||||
|
{0x0a, 0x05, "call"},
|
||||||
|
{0x07, 0x06, "callobj"},
|
||||||
|
{0x07, 0x07, "callobjx"},
|
||||||
|
{0x05, 0x08, "tjz"},
|
||||||
|
{0x05, 0x09, "djnz"},
|
||||||
|
{0x05, 0x0a, "jz"},
|
||||||
|
{0x05, 0x0b, "jnz"},
|
||||||
|
{0x00, 0x0c, "casedone"},
|
||||||
|
{0x08, 0x0d, "casevalue"},
|
||||||
|
{0x08, 0x0e, "caserange"},
|
||||||
|
{0x00, 0x0f, "lookdone"},
|
||||||
|
{0x00, 0x10, "lookupval"},
|
||||||
|
{0x00, 0x11, "lookdnval"},
|
||||||
|
{0x00, 0x12, "lookuprng"},
|
||||||
|
{0x00, 0x13, "lookdnrng"},
|
||||||
|
{0x00, 0x14, "pop"},
|
||||||
|
{0x00, 0x15, "run"},
|
||||||
|
{0x00, 0x16, "strsize"},
|
||||||
|
{0x00, 0x17, "strcomp"},
|
||||||
|
{0x00, 0x18, "bytefill"},
|
||||||
|
{0x00, 0x19, "wordfill"},
|
||||||
|
{0x00, 0x1a, "longfill"},
|
||||||
|
{0x00, 0x1b, "waitpeq"},
|
||||||
|
{0x00, 0x1c, "bytemove"},
|
||||||
|
{0x00, 0x1d, "wordmove"},
|
||||||
|
{0x00, 0x1e, "longmove"},
|
||||||
|
{0x00, 0x1f, "waitpne"},
|
||||||
|
{0x00, 0x20, "clkset"},
|
||||||
|
{0x00, 0x21, "cogstop"},
|
||||||
|
{0x00, 0x22, "lockret"},
|
||||||
|
{0x00, 0x23, "waitcnt"},
|
||||||
|
{0x00, 0x24, "ldregx"},
|
||||||
|
{0x00, 0x25, "stregx"},
|
||||||
|
{0x20, 0x26, "exregx"},
|
||||||
|
{0x00, 0x27, "waitvid"},
|
||||||
|
{0x00, 0x28, "coginitret"},
|
||||||
|
{0x00, 0x29, "locknewret"},
|
||||||
|
{0x00, 0x2a, "locksetret"},
|
||||||
|
{0x00, 0x2b, "lockclrret"},
|
||||||
|
{0x00, 0x2c, "coginit"},
|
||||||
|
{0x00, 0x2d, "locknew"},
|
||||||
|
{0x00, 0x2e, "lockset"},
|
||||||
|
{0x00, 0x2f, "lockclr"},
|
||||||
|
{0x00, 0x30, "abort"},
|
||||||
|
{0x00, 0x31, "abortval"},
|
||||||
|
{0x00, 0x32, "ret"},
|
||||||
|
{0x00, 0x33, "retval"},
|
||||||
|
{0x00, 0x34, "ldlim1"},
|
||||||
|
{0x00, 0x35, "ldli0"},
|
||||||
|
{0x00, 0x36, "ldli1"},
|
||||||
|
{0x09, 0x37, "ldlip"},
|
||||||
|
{0x0a, 0x38, "ldbi"},
|
||||||
|
{0x0b, 0x39, "ldwi"},
|
||||||
|
{0x0c, 0x3a, "ldmi"},
|
||||||
|
{0x0d, 0x3b, "ldli"},
|
||||||
|
{0x00, 0x3c, "lmm"},
|
||||||
|
{0x0f, 0x3d, "ldregbit"},
|
||||||
|
{0x0e, 0x3d, "stregbit"},
|
||||||
|
{0x0e, 0x3d, "exregbit"},
|
||||||
|
{0x0f, 0x3e, "ldregbits"},
|
||||||
|
{0x0e, 0x3e, "stregbits"},
|
||||||
|
{0x0e, 0x3e, "exregbits"},
|
||||||
|
{0x0f, 0x3f, "ldreg"},
|
||||||
|
{0x06, 0x3f, "streg"},
|
||||||
|
{0x0e, 0x3f, "exreg"},
|
||||||
|
{0x10, 0x40, "ldlvc"},
|
||||||
|
{0x10, 0x41, "stlvc"},
|
||||||
|
{0x30, 0x42, "exlvc"},
|
||||||
|
{0x10, 0x43, "lalvc"},
|
||||||
|
{0x11, 0x60, "ldllc"},
|
||||||
|
{0x11, 0x61, "stllc"},
|
||||||
|
{0x31, 0x62, "exllc"},
|
||||||
|
{0x11, 0x63, "lallc"},
|
||||||
|
{0x00, 0x80, "ldba"},
|
||||||
|
{0x00, 0x81, "stba"},
|
||||||
|
{0x20, 0x82, "exba"},
|
||||||
|
{0x00, 0x83, "laba"},
|
||||||
|
{0x01, 0x84, "ldbo"},
|
||||||
|
{0x01, 0x85, "stbo"},
|
||||||
|
{0x21, 0x86, "exbo"},
|
||||||
|
{0x01, 0x87, "labo"},
|
||||||
|
{0x02, 0x88, "ldbv"},
|
||||||
|
{0x02, 0x89, "stbv"},
|
||||||
|
{0x22, 0x8a, "exbv"},
|
||||||
|
{0x02, 0x8b, "labv"},
|
||||||
|
{0x03, 0x8c, "ldbl"},
|
||||||
|
{0x03, 0x8d, "stbl"},
|
||||||
|
{0x23, 0x8e, "exbl"},
|
||||||
|
{0x03, 0x8f, "labl"},
|
||||||
|
{0x00, 0x90, "ldbax"},
|
||||||
|
{0x00, 0x91, "stbax"},
|
||||||
|
{0x20, 0x92, "exbax"},
|
||||||
|
{0x00, 0x93, "labax"},
|
||||||
|
{0x01, 0x94, "ldbox"},
|
||||||
|
{0x01, 0x95, "stbox"},
|
||||||
|
{0x21, 0x96, "exbox"},
|
||||||
|
{0x01, 0x97, "labox"},
|
||||||
|
{0x02, 0x98, "ldbvx"},
|
||||||
|
{0x02, 0x99, "stbvx"},
|
||||||
|
{0x22, 0x9a, "exbvx"},
|
||||||
|
{0x02, 0x9b, "labvx"},
|
||||||
|
{0x03, 0x9c, "ldblx"},
|
||||||
|
{0x03, 0x9d, "stblx"},
|
||||||
|
{0x23, 0x9e, "exblx"},
|
||||||
|
{0x03, 0x9f, "lablx"},
|
||||||
|
{0x00, 0xa0, "ldwa"},
|
||||||
|
{0x00, 0xa1, "stwa"},
|
||||||
|
{0x20, 0xa2, "exwa"},
|
||||||
|
{0x00, 0xa3, "lawa"},
|
||||||
|
{0x01, 0xa4, "ldwo"},
|
||||||
|
{0x01, 0xa5, "stwo"},
|
||||||
|
{0x21, 0xa6, "exwo"},
|
||||||
|
{0x01, 0xa7, "lawo"},
|
||||||
|
{0x02, 0xa8, "ldwv"},
|
||||||
|
{0x02, 0xa9, "stwv"},
|
||||||
|
{0x22, 0xaa, "exwv"},
|
||||||
|
{0x02, 0xab, "lawv"},
|
||||||
|
{0x03, 0xac, "ldwl"},
|
||||||
|
{0x03, 0xad, "stwl"},
|
||||||
|
{0x23, 0xae, "exwl"},
|
||||||
|
{0x03, 0xaf, "lawl"},
|
||||||
|
{0x00, 0xb0, "ldwax"},
|
||||||
|
{0x00, 0xb1, "stwax"},
|
||||||
|
{0x20, 0xb2, "exwax"},
|
||||||
|
{0x00, 0xb3, "lawax"},
|
||||||
|
{0x01, 0xb4, "ldwox"},
|
||||||
|
{0x01, 0xb5, "stwox"},
|
||||||
|
{0x21, 0xb6, "exwox"},
|
||||||
|
{0x01, 0xb7, "lawox"},
|
||||||
|
{0x02, 0xb8, "ldwvx"},
|
||||||
|
{0x02, 0xb9, "stwvx"},
|
||||||
|
{0x22, 0xba, "exwvx"},
|
||||||
|
{0x02, 0xbb, "lawvx"},
|
||||||
|
{0x03, 0xbc, "ldwlx"},
|
||||||
|
{0x03, 0xbd, "stwlx"},
|
||||||
|
{0x23, 0xbe, "exwlx"},
|
||||||
|
{0x03, 0xbf, "lawlx"},
|
||||||
|
{0x00, 0xc0, "ldla"},
|
||||||
|
{0x00, 0xc1, "stla"},
|
||||||
|
{0x20, 0xc2, "exla"},
|
||||||
|
{0x00, 0xc3, "lala"},
|
||||||
|
{0x01, 0xc4, "ldlo"},
|
||||||
|
{0x01, 0xc5, "stlo"},
|
||||||
|
{0x21, 0xc6, "exlo"},
|
||||||
|
{0x01, 0xc7, "lalo"},
|
||||||
|
{0x02, 0xc8, "ldlv"},
|
||||||
|
{0x02, 0xc9, "stlv"},
|
||||||
|
{0x22, 0xca, "exlv"},
|
||||||
|
{0x02, 0xcb, "lalv"},
|
||||||
|
{0x03, 0xcc, "ldll"},
|
||||||
|
{0x03, 0xcd, "stll"},
|
||||||
|
{0x23, 0xce, "exll"},
|
||||||
|
{0x03, 0xcf, "lall"},
|
||||||
|
{0x00, 0xd0, "ldlax"},
|
||||||
|
{0x00, 0xd1, "stlax"},
|
||||||
|
{0x20, 0xd2, "exlax"},
|
||||||
|
{0x00, 0xd3, "lalax"},
|
||||||
|
{0x01, 0xd4, "ldlox"},
|
||||||
|
{0x01, 0xd5, "stlox"},
|
||||||
|
{0x21, 0xd6, "exlox"},
|
||||||
|
{0x01, 0xd7, "lalox"},
|
||||||
|
{0x02, 0xd8, "ldlvx"},
|
||||||
|
{0x02, 0xd9, "stlvx"},
|
||||||
|
{0x22, 0xda, "exlvx"},
|
||||||
|
{0x02, 0xdb, "lalvx"},
|
||||||
|
{0x03, 0xdc, "ldllx"},
|
||||||
|
{0x03, 0xdd, "stllx"},
|
||||||
|
{0x23, 0xde, "exllx"},
|
||||||
|
{0x03, 0xdf, "lallx"},
|
||||||
|
{0x40, 0xe0, "ror"},
|
||||||
|
{0x40, 0xe1, "rol"},
|
||||||
|
{0x40, 0xe2, "shr"},
|
||||||
|
{0x40, 0xe3, "shl"},
|
||||||
|
{0x40, 0xe4, "minlim"},
|
||||||
|
{0x40, 0xe5, "maxlim"},
|
||||||
|
{0x40, 0xe6, "neg"},
|
||||||
|
{0x40, 0xe7, "com"},
|
||||||
|
{0x40, 0xe8, "and"},
|
||||||
|
{0x40, 0xe9, "abs"},
|
||||||
|
{0x40, 0xea, "or"},
|
||||||
|
{0x40, 0xeb, "xor"},
|
||||||
|
{0x40, 0xec, "add"},
|
||||||
|
{0x40, 0xed, "sub"},
|
||||||
|
{0x40, 0xee, "sar"},
|
||||||
|
{0x40, 0xef, "rev"},
|
||||||
|
{0x40, 0xf0, "andl"},
|
||||||
|
{0x40, 0xf1, "encode"},
|
||||||
|
{0x40, 0xf2, "orl"},
|
||||||
|
{0x40, 0xf3, "decode"},
|
||||||
|
{0x40, 0xf4, "mul"},
|
||||||
|
{0x40, 0xf5, "mulh"},
|
||||||
|
{0x40, 0xf6, "div"},
|
||||||
|
{0x40, 0xf7, "mod"},
|
||||||
|
{0x40, 0xf8, "sqrt"},
|
||||||
|
{0x40, 0xf9, "cmplt"},
|
||||||
|
{0x40, 0xfa, "cmpgt"},
|
||||||
|
{0x40, 0xfb, "cmpne"},
|
||||||
|
{0x40, 0xfc, "cmpeq"},
|
||||||
|
{0x40, 0xfd, "cmple"},
|
||||||
|
{0x40, 0xfe, "cmpge"},
|
||||||
|
{0x40, 0xff, "notl"},
|
||||||
|
{0x60, 0x00, "store"},
|
||||||
|
{0x60, 0x02, "repeat"},
|
||||||
|
{0x60, 0x06, "repeats"},
|
||||||
|
{0x60, 0x08, "randf"},
|
||||||
|
{0x60, 0x0c, "randr"},
|
||||||
|
{0x60, 0x10, "sexb"},
|
||||||
|
{0x60, 0x14, "sexw"},
|
||||||
|
{0x60, 0x18, "postclr"},
|
||||||
|
{0x60, 0x1c, "postset"},
|
||||||
|
{0x60, 0x20, "preinc"},
|
||||||
|
{0x60, 0x28, "postinc"},
|
||||||
|
{0x60, 0x30, "predec"},
|
||||||
|
{0x60, 0x38, "postdec"},
|
||||||
|
{0, 0, 0}};
|
||||||
|
/*
|
||||||
|
+ -----------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
Binary file not shown.
|
@ -0,0 +1,243 @@
|
||||||
|
'**********************************************
|
||||||
|
' Dhrystone 1.1
|
||||||
|
'**********************************************
|
||||||
|
|
||||||
|
OBJ
|
||||||
|
ser : "Simple_Serial"
|
||||||
|
|
||||||
|
CON
|
||||||
|
_clkmode = xtal1+pll16x
|
||||||
|
_clkfreq = 80000000
|
||||||
|
LOOPS = 500
|
||||||
|
|
||||||
|
Ident1 = 1
|
||||||
|
Ident2 = 2
|
||||||
|
Ident3 = 3
|
||||||
|
Ident4 = 4
|
||||||
|
Ident5 = 5
|
||||||
|
|
||||||
|
' typedef struct Record
|
||||||
|
PtrComp = 0
|
||||||
|
Discr = 4
|
||||||
|
EnumComp = 8
|
||||||
|
IntComp = 12
|
||||||
|
StringComp = 16
|
||||||
|
|
||||||
|
NULL = 0
|
||||||
|
|
||||||
|
DAT
|
||||||
|
Version byte "1.1", 0
|
||||||
|
Array1Glob long 0[51]
|
||||||
|
Array2Glob long 0[51*51]
|
||||||
|
xxx long 0[12]
|
||||||
|
yyy long 0[12]
|
||||||
|
PtrGlb long 0
|
||||||
|
PtrGlbNext long 0
|
||||||
|
IntGlob long 0
|
||||||
|
BoolGlob long 0
|
||||||
|
Char1Glob long 0
|
||||||
|
Char2Glob long 0
|
||||||
|
String1Loc long 0[8]
|
||||||
|
String2Loc long 0[8]
|
||||||
|
starttime long 0
|
||||||
|
benchtime long 0
|
||||||
|
nulltime long 0
|
||||||
|
|
||||||
|
PUB Dhrystone11
|
||||||
|
|
||||||
|
PtrGlb := @xxx
|
||||||
|
PtrGlbNext := @yyy
|
||||||
|
Proc0
|
||||||
|
|
||||||
|
{
|
||||||
|
* Package 1
|
||||||
|
}
|
||||||
|
PUB Proc0 | IntLoc1, IntLoc2, IntLoc3, CharLoc, CharIndex, EnumLoc, i
|
||||||
|
starttime := time_msec
|
||||||
|
i := 0
|
||||||
|
repeat while (i < LOOPS)
|
||||||
|
++i
|
||||||
|
nulltime := time_msec - starttime { Computes o'head of loop }
|
||||||
|
long[PtrGlb + PtrComp] := PtrGlbNext
|
||||||
|
long[PtrGlb + Discr] := Ident1
|
||||||
|
long[PtrGlb + EnumComp] := Ident3
|
||||||
|
long[PtrGlb + IntComp] := 40
|
||||||
|
strcpy((PtrGlb + StringComp), string("DHRYSTONE PROGRAM, SOME STRING"))
|
||||||
|
strcpy(@String1Loc, string("DHRYSTONE PROGRAM, 1'ST STRING")) {GOOF}
|
||||||
|
long[@Array2Glob][8 * 51 + 7] := 10 { Was missing in published program }
|
||||||
|
{****************
|
||||||
|
-- Start Timer --
|
||||||
|
****************}
|
||||||
|
starttime := time_msec
|
||||||
|
i := 0
|
||||||
|
repeat while (i < LOOPS)
|
||||||
|
Proc5
|
||||||
|
Proc4
|
||||||
|
IntLoc1 := 2
|
||||||
|
IntLoc2 := 3
|
||||||
|
strcpy(@String2Loc, string("DHRYSTONE PROGRAM, 2'ND STRING"))
|
||||||
|
EnumLoc := Ident2
|
||||||
|
BoolGlob := not Func2(@String1Loc, @String2Loc)
|
||||||
|
repeat while (IntLoc1 < IntLoc2)
|
||||||
|
IntLoc3 := 5 * IntLoc1 - IntLoc2
|
||||||
|
Proc7(IntLoc1, IntLoc2, @IntLoc3)
|
||||||
|
++IntLoc1
|
||||||
|
Proc8(@Array1Glob, @Array2Glob, IntLoc1, IntLoc3)
|
||||||
|
Proc1(PtrGlb)
|
||||||
|
byte[@CharIndex] := "A"
|
||||||
|
repeat while (byte[@CharIndex] =< Char2Glob)
|
||||||
|
if (EnumLoc == Func1(byte[@CharIndex], "C"))
|
||||||
|
Proc6(Ident1, @EnumLoc)
|
||||||
|
byte[@CharIndex] := byte[@charIndex] + 1
|
||||||
|
IntLoc3 := IntLoc2 * IntLoc1
|
||||||
|
IntLoc2 := IntLoc3 / IntLoc1
|
||||||
|
IntLoc2 := 7 *(IntLoc3 - IntLoc2) - IntLoc1
|
||||||
|
Proc2(@IntLoc1)
|
||||||
|
++i
|
||||||
|
{****************
|
||||||
|
-- Stop Timer --
|
||||||
|
****************}
|
||||||
|
benchtime := time_msec - starttime - nulltime
|
||||||
|
ser.str(string("Dhrystone("))
|
||||||
|
ser.str(@Version)
|
||||||
|
ser.str(string(") time for "))
|
||||||
|
ser.dec(LOOPS)
|
||||||
|
ser.str(string(" passes = "))
|
||||||
|
ser.dec(benchtime)
|
||||||
|
ser.str(string(" msec", 13))
|
||||||
|
ser.str(string("This machine benchmarks at "))
|
||||||
|
ser.dec(LOOPS * 1000 / benchtime)
|
||||||
|
ser.str(string(" dhrystones/second", 13))
|
||||||
|
|
||||||
|
PUB Proc1(PtrParIn)
|
||||||
|
memcpy(long[PtrParIn + PtrComp], PtrGlb, 48)
|
||||||
|
long[PtrParIn + IntComp] := 5
|
||||||
|
long[long[PtrParIn + PtrComp] + IntComp] := long[PtrParIn + IntComp]
|
||||||
|
long[long[PtrParIn + PtrComp] + PtrComp] := long[PtrParIn + PtrComp]
|
||||||
|
Proc3(long[long[PtrParIn + PtrComp] + PtrComp])
|
||||||
|
if (long[long[PtrParIn + PtrComp] + Discr] == Ident1)
|
||||||
|
long[long[PtrParIn + PtrComp] + IntComp] := 6
|
||||||
|
Proc6(long[PtrParIn + EnumComp], long[PtrParIn + PtrComp] + EnumComp)
|
||||||
|
long[long[PtrParIn + PtrComp] + PtrComp] := long[PtrGlb + PtrComp]
|
||||||
|
Proc7(long[long[PtrParIn + PtrComp] + IntComp], 10, long[PtrParIn + PtrComp] + IntComp)
|
||||||
|
else
|
||||||
|
memcpy(PtrParIn, long[PtrParIn + PtrComp], 48)
|
||||||
|
|
||||||
|
PUB Proc2(IntParIO) | IntLoc, EnumLoc
|
||||||
|
IntLoc := long[IntParIO] + 10
|
||||||
|
|
||||||
|
repeat 'while ()
|
||||||
|
if (Char1Glob == "A")
|
||||||
|
--IntLoc
|
||||||
|
long[IntParIO] := IntLoc - IntGlob
|
||||||
|
EnumLoc := Ident1
|
||||||
|
if (EnumLoc == Ident1)
|
||||||
|
quit
|
||||||
|
|
||||||
|
PUB Proc3(PtrParOut)
|
||||||
|
if (PtrGlb <> NULL)
|
||||||
|
PtrParOut := long[PtrGlb + PtrComp]
|
||||||
|
else
|
||||||
|
IntGlob := 100
|
||||||
|
Proc7(10, IntGlob, PtrGlb + IntComp)
|
||||||
|
|
||||||
|
PUB Proc4 | BoolLoc
|
||||||
|
BoolLoc := Char1Glob == "A"
|
||||||
|
BoolLoc |= BoolGlob
|
||||||
|
Char2Glob := "B"
|
||||||
|
|
||||||
|
PUB Proc5
|
||||||
|
Char1Glob := "A"
|
||||||
|
BoolGlob := FALSE
|
||||||
|
|
||||||
|
PUB Proc6(EnumParIn, EnumParOut)
|
||||||
|
long[EnumParOut] := EnumParIn
|
||||||
|
ifnot Func3(EnumParIn)
|
||||||
|
long[EnumParOut] := Ident4
|
||||||
|
if EnumParIn == Ident1
|
||||||
|
long[EnumParOut] := Ident1
|
||||||
|
elseif EnumParIn == Ident2
|
||||||
|
if (IntGlob > 100)
|
||||||
|
long[EnumParOut] := Ident1
|
||||||
|
else
|
||||||
|
long[EnumParOut] := Ident4
|
||||||
|
elseif EnumParIn == Ident3
|
||||||
|
long[EnumParOut] := Ident2
|
||||||
|
elseif (EnumParIn == Ident4) or (EnumParIn == Ident5)
|
||||||
|
long[EnumParOut] := Ident3
|
||||||
|
|
||||||
|
PUB Proc7(IntParI1, IntParI2, IntParOut) | IntLoc
|
||||||
|
IntLoc := IntParI1 + 2
|
||||||
|
long[IntParOut] := IntParI2 + IntLoc
|
||||||
|
|
||||||
|
PUB Proc8(Array1Par, Array2Par, IntParI1, IntParI2) | IntLoc, IntIndex
|
||||||
|
IntLoc := IntParI1 + 5
|
||||||
|
long[Array1Par][IntLoc] := IntParI2
|
||||||
|
long[Array1Par][IntLoc + 1] := long[Array1Par][IntLoc]
|
||||||
|
long[Array1Par][IntLoc + 30] := IntLoc
|
||||||
|
IntIndex := IntLoc
|
||||||
|
repeat while (IntIndex =<(IntLoc + 1))
|
||||||
|
long[Array2Par][IntLoc * 51 + IntIndex] := IntLoc
|
||||||
|
++IntIndex
|
||||||
|
++long[Array2Par][IntLoc * 51 + IntLoc - 1]
|
||||||
|
long[Array2Par][(IntLoc + 20) * 51 + IntLoc] := long[Array1Par][IntLoc]
|
||||||
|
IntGlob := 5
|
||||||
|
|
||||||
|
PUB Func1(CharPar1, CharPar2) | CharLoc1, CharLoc2
|
||||||
|
byte[@CharLoc1] := byte[@CharPar1]
|
||||||
|
byte[@CharLoc2] := byte[@CharLoc1]
|
||||||
|
if (byte[@CharLoc2] <> byte[@CharPar2])
|
||||||
|
return (Ident1)
|
||||||
|
else
|
||||||
|
return (Ident2)
|
||||||
|
|
||||||
|
PUB Func2(StrParI1, StrParI2) | IntLoc, CharLoc
|
||||||
|
IntLoc := 1
|
||||||
|
repeat while (IntLoc =< 1)
|
||||||
|
if (Func1(byte[StrParI1][IntLoc], byte[StrParI2][IntLoc + 1]) == Ident1)
|
||||||
|
byte[@CharLoc] := "A"
|
||||||
|
++IntLoc
|
||||||
|
if (byte[@CharLoc] => "W" and byte[@CharLoc] =< "Z")
|
||||||
|
IntLoc := 7
|
||||||
|
if (byte[@CharLoc] == "X")
|
||||||
|
return (TRUE)
|
||||||
|
else
|
||||||
|
if (strcmp(StrParI1, StrParI2) > 0)
|
||||||
|
IntLoc += 7
|
||||||
|
return (TRUE)
|
||||||
|
else
|
||||||
|
return (FALSE)
|
||||||
|
|
||||||
|
PUB Func3(EnumParIn) | EnumLoc
|
||||||
|
EnumLoc := EnumParIn
|
||||||
|
if (EnumLoc == Ident3)
|
||||||
|
return (TRUE)
|
||||||
|
return (FALSE)
|
||||||
|
|
||||||
|
PUB strcpy(dst, src)
|
||||||
|
bytemove(dst, src, strsize(src) + 1)
|
||||||
|
{
|
||||||
|
repeat strsize(src)
|
||||||
|
byte[dst++] := byte[src++]
|
||||||
|
}
|
||||||
|
|
||||||
|
PUB memcpy(dst, src, num)
|
||||||
|
bytemove(dst, src, num)
|
||||||
|
{
|
||||||
|
repeat num
|
||||||
|
byte[dst++] := byte[src++]
|
||||||
|
}
|
||||||
|
|
||||||
|
PUB strcmp(str1, str2)
|
||||||
|
result := not strcomp(str1, str2)
|
||||||
|
{
|
||||||
|
repeat while byte[str1]
|
||||||
|
if byte[str1] <> byte[str2]
|
||||||
|
quit
|
||||||
|
str1++
|
||||||
|
str2++
|
||||||
|
return byte[str1] - byte[str2]
|
||||||
|
}
|
||||||
|
|
||||||
|
PUB time_msec
|
||||||
|
return cnt / (_clkfreq/1000)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,351 @@
|
||||||
|
SPASM(1) User Commands SPASM(1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
spasm - spin assembler
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
spasm [-l] [-d] FILE
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Spasm assembles the source file given by FILE. The file name may
|
||||||
|
include the extension, or .spa will be assumed if no extension is
|
||||||
|
specified. The assembled binary program will written to a file with
|
||||||
|
the same root name plus a .bin extension. If -l is specified, it will
|
||||||
|
print an assembly listing. If -d is specified, spasm will print debug
|
||||||
|
information.
|
||||||
|
|
||||||
|
Spasm is an assembly language that defines mnemonics for Spin
|
||||||
|
bytecodes. Spin bytecodes are executed by the Spin interpreter, which
|
||||||
|
is loaded at boot time from the internal ROM. The Spin interpreter is
|
||||||
|
a stack-based virtual machine that uses the stack to store parameters
|
||||||
|
that are used by operators, such as add, sub, etc. The operators store
|
||||||
|
their results back onto the stack. There are other operators that
|
||||||
|
transfer data back and forth between the stack and hub RAM.
|
||||||
|
|
||||||
|
The Spin bytecodes are listed below. They are separated into four
|
||||||
|
major groups -- lower, memory, math and extened operators. The lower
|
||||||
|
group contains a mix of operators, including those that handle program
|
||||||
|
flow, lookup, lookdown, case, and several other miscellaneous functions.
|
||||||
|
The math operators implement the various math and logic functions that
|
||||||
|
use two arguments.
|
||||||
|
|
||||||
|
The memory operators implement load, store, execute and address
|
||||||
|
functions. A load operation reads data from the hub RAM and pushes it
|
||||||
|
onto the stack. A store operation pops a value off the stack and
|
||||||
|
stores it in RAM. The address operator is used to push the absolute
|
||||||
|
address of a hub RAM location onto the stack.
|
||||||
|
|
||||||
|
The execute operation is used to execute an operation directly on a RAM
|
||||||
|
location. The result can be optionally pushed to the stack. The
|
||||||
|
operations that can be executed directly on a hub RAM location include
|
||||||
|
the standard 32 math operations plus a small number of extended
|
||||||
|
operations. The extended operators include pre and post increment and
|
||||||
|
decrement, sign extension and the random function.
|
||||||
|
|
||||||
|
The format of the memory mnemonics is as follows:
|
||||||
|
|
||||||
|
<operation><size><type><mode>
|
||||||
|
operation = {ld, st, ex, la},
|
||||||
|
size = {b, w, l},
|
||||||
|
type = {i, l, o, a, v, s}
|
||||||
|
mode = {c, x, 0, 1, m1, p}
|
||||||
|
|
||||||
|
The operations are load, store, execute and load address as stated
|
||||||
|
earlier. The size refers to byte, word and long. The types are
|
||||||
|
immediate, local, object, absolute, variable and stack. The modes
|
||||||
|
are compact, indexed, zero, one, minus one and packed.
|
||||||
|
|
||||||
|
As an example, the instruction ldwi means load-word-immediate. It
|
||||||
|
will load an immediate value onto the stack. The instruction stba
|
||||||
|
will store a byte at the absolute address residing in the stack.
|
||||||
|
|
||||||
|
There are compact instructions that use a single byte to address
|
||||||
|
the first 8 long values residing in the method's stack frame or in
|
||||||
|
an object's variable space. These use the size, type and mode
|
||||||
|
characters "llc". As an example, the method result value can be
|
||||||
|
set with the "stllc 0" instruction. The fourth long in the objet's
|
||||||
|
variable section could be loaded with "ldllc 12".
|
||||||
|
|
||||||
|
When an execute memory operation is specified it is followed by one of
|
||||||
|
the math operators or an extended operator. An execute instruction may
|
||||||
|
also specify the "load" extended operator to save the result on the
|
||||||
|
stack. Examples of using execute instructions are as follows:
|
||||||
|
|
||||||
|
exlo $8 add ' Add value on stack to the object long at offset $8
|
||||||
|
exwv $20 preinc ' Increment the VAR word at offset $20
|
||||||
|
exll $10 postdec load ' Decrement stack location $10 and load
|
||||||
|
|
||||||
|
Spasm also includes psuedo-ops, which are shortened versions of the
|
||||||
|
memory mnenomics. The psuedo-ops are made up only of the operation
|
||||||
|
and size fields, plus the "x" charater if it is indexed. The
|
||||||
|
psuedo-ops are mapped to explicit opcodes depending on the context
|
||||||
|
of the operand. As an example "ldl 1" maps into "ldli1", and
|
||||||
|
"ldl result" maps into "ldllc 0".
|
||||||
|
|
||||||
|
The Spasm opcodes are listed below. The offsets used for the jump
|
||||||
|
instructions are signed offsets that are relative to the address of the
|
||||||
|
next instruction. A "jmp 0" instruction will just execute the next
|
||||||
|
instruction.
|
||||||
|
|
||||||
|
Signed offsets are encoded in either one or two bytes depending
|
||||||
|
on the value of the most significant bit in the first byte. If the
|
||||||
|
MSB is zero the remaining seven bits are treated as a signed 7-bit
|
||||||
|
number in the range from -64 to 63. If the MSB is non-zero, the
|
||||||
|
remaining seven bits are used as the most significant bits of a 15-bit
|
||||||
|
signed number, and the next byte provides the eight least sigficant
|
||||||
|
bits. The 15-bit signed offset has a range from -16384 to 16383.
|
||||||
|
|
||||||
|
The memory opcodes use an unsigned offset that can also be encoded in
|
||||||
|
one or two bytes. The MSB is used to determine whether it is one or
|
||||||
|
two bytes just like for signed offset. However, since it is unsigned,
|
||||||
|
the range for the one-byte offset is 0 to 128, and for two bytes it is
|
||||||
|
0 to 32768.
|
||||||
|
|
||||||
|
Lower Opcodes
|
||||||
|
-------------
|
||||||
|
00 ldfrmr - Load call frame with return value required
|
||||||
|
01 ldfrm - Load call frame
|
||||||
|
02 ldfrmar - Load call frame with abort trap & return value
|
||||||
|
03 ldfrma - Load call frame with abort trap
|
||||||
|
04 jmp offset - Jump to signed object offset
|
||||||
|
05 call meth - Call method
|
||||||
|
06 callobj meth, obj - Call method in object
|
||||||
|
07 callobjx meth, obj - Call method in object with index
|
||||||
|
08 tjz offset - Test and jump if zero
|
||||||
|
09 djnz offset - Decrement and jump if not zero
|
||||||
|
0a jz offset - Jump if zero
|
||||||
|
0b jnz offset - Jump if not zero
|
||||||
|
0c casedone - Case done without a match
|
||||||
|
0d casevalue - Execute if value matches case value
|
||||||
|
0e caserange - Execute if case value within range
|
||||||
|
0f lookdone - Look up/down done without a match
|
||||||
|
10 lookupval -
|
||||||
|
11 lookdnval
|
||||||
|
12 lookuprng
|
||||||
|
13 lookdnrng
|
||||||
|
14 pop - Discard N bytes from the stack
|
||||||
|
15 run - Prepare new spin cog stack for execution
|
||||||
|
16 strsize - Determine the size of a string
|
||||||
|
17 strcomp - Compare two strings
|
||||||
|
18 bytefill - Fill memory with a constant byte value
|
||||||
|
19 wordfill - Fill memory with a constant word value
|
||||||
|
1a longfill - Fill memory with a constant long value
|
||||||
|
1b waitpeq - Wait till pins are equal to a value
|
||||||
|
1c bytemove - Copy bytes to a new location
|
||||||
|
1d wordmove - Copy words to a new location
|
||||||
|
1e longmove - Copy longs to a new location
|
||||||
|
1f waitpne - Wait till pins are not equal to value
|
||||||
|
20 clkset - Change the clock frequency and mode
|
||||||
|
21 cogstop - Stop the specified cog
|
||||||
|
22 lockret - Return a lock
|
||||||
|
23 waitcnt - Wait for cnt to equal a specified value
|
||||||
|
24 ldlsx
|
||||||
|
25 stlsx
|
||||||
|
26 exlsx
|
||||||
|
27 waitvid - Wait on video
|
||||||
|
28 coginitret - Start a cog and return the cog number
|
||||||
|
29 locknewret - Allocate a lock and return the lock number
|
||||||
|
2a locksetret - Set a lock and return the previous value
|
||||||
|
2b lockclrret - Clear a lock and return the previous value
|
||||||
|
2c coginit - Start a cog
|
||||||
|
2d locknew - Allocate a lock with no return value
|
||||||
|
2e lockset - Set a lock with no return value
|
||||||
|
2f lockclr - Clear a lock with no return value
|
||||||
|
30 abort - Perform an abort to the next abort trap
|
||||||
|
31 abortval - Perform an abort and return a value
|
||||||
|
32 ret - Return without loading a return value
|
||||||
|
33 retval - Return and load a return value on the stack
|
||||||
|
34 ldlim1 - Load a minus 1
|
||||||
|
35 ldli0 - Load zero
|
||||||
|
36 ldli1 - Load 1
|
||||||
|
37 ldlip value - Load a packed-byte constant
|
||||||
|
38 ldbi value - Load a single-byte constant
|
||||||
|
39 ldwi value - Load a two-byte constant
|
||||||
|
3a ldmi value - Load a three-byte constant
|
||||||
|
3b ldli value - Load a four-byte constant
|
||||||
|
3c --- - Unused opcode
|
||||||
|
3d ldregbit - Load a bit from a register
|
||||||
|
3d stregbit - Store a bit to a register
|
||||||
|
3e ldregbits - Load bits from a register
|
||||||
|
3e stregbits - Store bit to a register
|
||||||
|
3f ldreg - Load a register
|
||||||
|
3f streg - Store a register
|
||||||
|
|
||||||
|
Compact Memory Opcodes
|
||||||
|
--------------
|
||||||
|
40 ldlvc offset - Load long variable compact
|
||||||
|
41 stlvc offset - Store long variable compact
|
||||||
|
42 exlvc offset - Execute on a long variable compact
|
||||||
|
43 lalvc offset - Load address of a long variable compact
|
||||||
|
60 ldllc offset - Load long local compact
|
||||||
|
61 stllc offset - Store long local compact
|
||||||
|
62 exllc offset - Execute on a long local compact
|
||||||
|
63 lallc offset - Load address of a long local compact
|
||||||
|
|
||||||
|
Byte Memory Opcodes
|
||||||
|
--------------
|
||||||
|
80 ldba - Load byte absolute
|
||||||
|
81 stba - Store byte absolute
|
||||||
|
82 exba - Execute on a byte absolute
|
||||||
|
83 laba - Load address of a byte absolute
|
||||||
|
84 ldbo offset - Load byte object offset
|
||||||
|
85 stbo offset
|
||||||
|
86 exbo offset
|
||||||
|
87 labo offset
|
||||||
|
88 ldbv offset - Load byte variable offset
|
||||||
|
89 stbv offset
|
||||||
|
8a exbv offset
|
||||||
|
8b labv offset
|
||||||
|
8c ldbl offset - Load byte local offset
|
||||||
|
8d stbl offset
|
||||||
|
8e exbl offset
|
||||||
|
8f labl offset
|
||||||
|
90 ldbax - Load byte absolute with index
|
||||||
|
91 stbax
|
||||||
|
92 exbax
|
||||||
|
93 labax
|
||||||
|
94 ldbox offset - Load byte object offset with index
|
||||||
|
95 stbox offset
|
||||||
|
96 exbox offset
|
||||||
|
97 labox offset
|
||||||
|
98 ldbvx offset - Load byte variable offset with index
|
||||||
|
99 stbvx offset
|
||||||
|
9a exbvx offset
|
||||||
|
9b labvx offset
|
||||||
|
9c ldblx offset - Load byte local offset with index
|
||||||
|
9d stblx offset
|
||||||
|
9e exblx offset
|
||||||
|
9f lablx offset
|
||||||
|
|
||||||
|
Word Memory Opcodes
|
||||||
|
-------------------
|
||||||
|
a0 ldwa - Load word absolute
|
||||||
|
a1 stwa
|
||||||
|
a2 exwa
|
||||||
|
a3 lawa
|
||||||
|
a4 ldwo offset
|
||||||
|
a5 stwo offset
|
||||||
|
a6 exwo offset
|
||||||
|
a7 lawo offset
|
||||||
|
a8 ldwv offset
|
||||||
|
a9 stwv offset
|
||||||
|
aa exwv offset
|
||||||
|
ab lawv offset
|
||||||
|
ac ldwl offset
|
||||||
|
ad stwl offset
|
||||||
|
ae exwl offset
|
||||||
|
af lawl offset
|
||||||
|
b0 ldwax - Load word absolute with index
|
||||||
|
b1 stwax
|
||||||
|
b2 exwax
|
||||||
|
b3 lawax
|
||||||
|
b4 ldwox offset
|
||||||
|
b5 stwox offset
|
||||||
|
b6 exwox offset
|
||||||
|
b7 lawox offset
|
||||||
|
b8 ldwvx offset
|
||||||
|
b9 stwvx offset
|
||||||
|
ba exwvx offset
|
||||||
|
bb lawvx offset
|
||||||
|
bc ldwlx offset
|
||||||
|
bd stwlx offset
|
||||||
|
be exwlx offset
|
||||||
|
bf lawlx offset
|
||||||
|
|
||||||
|
Long Memory Opcodes
|
||||||
|
-------------------
|
||||||
|
c0 ldla - Load long absolute
|
||||||
|
c1 stla
|
||||||
|
c2 exla
|
||||||
|
c3 lala
|
||||||
|
c4 ldlo offset
|
||||||
|
c5 stlo offset
|
||||||
|
c6 exlo offset
|
||||||
|
c7 lalo offset
|
||||||
|
c8 ldlv offset
|
||||||
|
c9 stlv offset
|
||||||
|
ca exlv offset
|
||||||
|
cb lalv offset
|
||||||
|
cc ldll offset
|
||||||
|
cd stll offset
|
||||||
|
ce exll offset
|
||||||
|
cf lall offset
|
||||||
|
d0 ldlax - Load long absolute with index
|
||||||
|
d1 stlax
|
||||||
|
d2 exlax
|
||||||
|
d3 lalax
|
||||||
|
d4 ldlox offset
|
||||||
|
d5 stlox offset
|
||||||
|
d6 exlox offset
|
||||||
|
d7 lalox offset
|
||||||
|
d8 ldlvx offset
|
||||||
|
d9 stlvx offset
|
||||||
|
da exlvx offset
|
||||||
|
db lalvx offset
|
||||||
|
dc ldllx offset
|
||||||
|
dd stllx offset
|
||||||
|
de exllx offset
|
||||||
|
df lallx offset
|
||||||
|
|
||||||
|
Math Opcodes
|
||||||
|
------------
|
||||||
|
e0 ror - Rotate right
|
||||||
|
e1 rol - Rotate left
|
||||||
|
e2 shr - Shift right
|
||||||
|
e3 shl - Shift left
|
||||||
|
e4 min - Maximum
|
||||||
|
e5 max - Minimum
|
||||||
|
e6 neg - Negate
|
||||||
|
e7 com - Compliment
|
||||||
|
e8 and - Bitwise and
|
||||||
|
e9 abs - Absolute value
|
||||||
|
ea or - Bitwise or
|
||||||
|
eb xor - Bitwise exclusive or
|
||||||
|
ec add - Add
|
||||||
|
ed sub - Subtract
|
||||||
|
ee sar - Shift arithmetic right
|
||||||
|
ef rev - Bit reverse
|
||||||
|
f0 andl - Logical and
|
||||||
|
f1 encode - Shift "1" left
|
||||||
|
f2 orl - Logical or
|
||||||
|
f3 decode - Find left-most "1" bit
|
||||||
|
f4 mul - Multiply
|
||||||
|
f5 mulh - Multiply high
|
||||||
|
f6 div - Divide
|
||||||
|
f7 mod - Modulus
|
||||||
|
f8 sqrt - Square root
|
||||||
|
f9 cmplt - Less than
|
||||||
|
fa cmpgt - Greater than
|
||||||
|
fb cmpne - Not equal
|
||||||
|
fc cmpeq - Equal
|
||||||
|
fd cmple - Less than or equal
|
||||||
|
fe cmpge - Greater than or equal
|
||||||
|
ff notl - Logical not
|
||||||
|
|
||||||
|
Extended opcodes
|
||||||
|
----------------
|
||||||
|
00 load - Load the value
|
||||||
|
02 repeat - Repeat index from first to last
|
||||||
|
06 repeats - Repeat index from first to last with step
|
||||||
|
08 randf - Forward random number
|
||||||
|
0c randr - Reverse random number
|
||||||
|
10 sexb - Sign extend byte
|
||||||
|
14 sexw - Sign extend word
|
||||||
|
18 postclr - Post clear to zero
|
||||||
|
1c postset - Post set to all ones
|
||||||
|
26 preinc - Pre-increment
|
||||||
|
2e postinc - Post-increment
|
||||||
|
36 predec - Pre-decrement
|
||||||
|
3e postdec - Post-decrement
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
Dave Hein
|
||||||
|
|
||||||
|
COPYRIGHT
|
||||||
|
Copyright (c) 2011, 2012, Dave Hein
|
||||||
|
MIT License (See license.txt in the root directory)
|
||||||
|
This is free software: you are free to change and redistribute it.
|
||||||
|
There is no warranty, to the extent permitted by law.
|
||||||
|
|
||||||
|
|
||||||
|
SPASM March 2012 SPASM(1)
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
||||||
|
CON
|
||||||
|
_clkmode = xtal1+pll16x
|
||||||
|
_clkfreq = 80_000_000
|
||||||
|
|
||||||
|
OBJ
|
||||||
|
ser : "Simple_Serial"
|
||||||
|
dry : "dry11"
|
||||||
|
|
||||||
|
PUB main | ptr, count
|
||||||
|
'waitcnt(clkfreq*3+cnt)
|
||||||
|
ser.init(31, 30, 19200)
|
||||||
|
ser.str(string(13, "Testing Spin Interpreter", 13))
|
||||||
|
dry.Dhrystone11
|
||||||
|
waitcnt(clkfreq/10+cnt)
|
|
@ -0,0 +1,231 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.21
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "interp.h"
|
||||||
|
|
||||||
|
char *FindChar(char *str, int32_t val);
|
||||||
|
int32_t CheckWaitFlag(PasmVarsT *pasmvars, int mode);
|
||||||
|
|
||||||
|
extern char *hubram;
|
||||||
|
extern int32_t memsize;
|
||||||
|
extern int32_t loopcount;
|
||||||
|
extern int32_t cycleaccurate;
|
||||||
|
|
||||||
|
extern FILE *tracefile;
|
||||||
|
|
||||||
|
static char *condnames[16] = {
|
||||||
|
"if_never ", "if_nz_and_nc", "if_z_and_nc ", "if_nc ",
|
||||||
|
"if_nz_and_c ", "if_nz ", "if_z_ne_c ", "if_nz_or_nc ",
|
||||||
|
"if_z_and_c ", "if_z_eq_c ", "if_z ", "if_z_or_nc ",
|
||||||
|
"if_c ", "if_nz_or_c ", "if_z_or_c ", " "};
|
||||||
|
|
||||||
|
|
||||||
|
static char *opnames[64][2] = {
|
||||||
|
{"wrbyte", "rdbyte"}, {"wrword", "rdword"}, {"wrlong", "rdlong"},
|
||||||
|
{"hubop nr", "hubop"}, {"undef nr", "undef"}, {"undef nr", "undef"},
|
||||||
|
{"undef nr", "undef"}, {"undef nr", "undef"}, {"ror nr", "ror"},
|
||||||
|
{"rol nr", "rol"}, {"shr nr", "shr"}, {"shl nr", "shl"},
|
||||||
|
{"rcr nr", "rcr"}, {"rcl nr", "rcl"}, {"sar nr", "sar"},
|
||||||
|
{"rev nr", "rev"}, {"mins nr", "mins"}, {"maxs nr", "maxs"},
|
||||||
|
{"min nr", "min"}, {"max nr", "max"}, {"movs nr", "movs"},
|
||||||
|
{"movd nr", "movd"}, {"movi nr", "movi"}, {"jmp", "call"},
|
||||||
|
{"test", "and"}, {"testn", "andn"}, {"or nr", "or"},
|
||||||
|
{"xor nr", "xor"}, {"muxc nr", "muxc"}, {"muxnc nr", "muxnc"},
|
||||||
|
{"muxz nr", "muxz"}, {"muxnz nr", "muxnz"}, {"add nr", "add"},
|
||||||
|
{"cmp", "sub"}, {"addabs nr", "addabs"}, {"subabs nr", "subabs"},
|
||||||
|
{"sumc nr", "sumc"}, {"sumnc nr", "sumnc"}, {"sumz nr", "sumz"},
|
||||||
|
{"sumnz nr", "sumnz"}, {"mov nr", "mov"}, {"neg nr", "neg"},
|
||||||
|
{"abs nr", "abs"}, {"absneg nr", "absneg"}, {"negc nr", "negc"},
|
||||||
|
{"negnc nr", "negnc"}, {"negz nr", "negz"}, {"negnz nr", "negnz"},
|
||||||
|
{"cmps", "cmps wr"}, {"cmpsx", "cmpsx wr"}, {"addx nr", "addx"},
|
||||||
|
{"cmpx", "subx"}, {"adds nr", "adds"}, {"subs nr", "subs"},
|
||||||
|
{"addsx nr", "addsx"}, {"subsx nr", "subsx"}, {"cmpsub nr", "cmpsub"},
|
||||||
|
{"djnz nr", "djnz"}, {"tjnz", "tjnz wr"}, {"tjz", "tjz wr"},
|
||||||
|
{"waitpeq", "waitpeq wr"}, {"waitpne", "waitpne wr"},
|
||||||
|
{"waitcnt nr", "waitcnt"}, {"waitvid", "waitvid wr"}};
|
||||||
|
|
||||||
|
static char *hubops[8][2] = {
|
||||||
|
{"clkset", "clkset wr"}, {"cogid nr", "cogid"},
|
||||||
|
{"coginit", "coginit wr"}, {"cogstop", "cogstop wr"},
|
||||||
|
{"locknew nr", "locknew"}, {"lockret", "lockret wr"},
|
||||||
|
{"lockset", "lockset wr"}, {"lockclr", "lockclr wr"}};
|
||||||
|
|
||||||
|
static int32_t swapshift[32] = {
|
||||||
|
28, 23, 8, 16, 21, 7, 21, 7, 3, 7, 13, 9, 19, 4,-13, 15,
|
||||||
|
-8,-17, -3, 7, 2, -8,-16, 6,-21,-16, -8,-23,-26,-22,-25,-10};
|
||||||
|
|
||||||
|
static uint32_t swapmask[32] = {
|
||||||
|
0x00000008, 0x00000080, 0x00200000, 0x00001000, 0x00000040, 0x00080000,
|
||||||
|
0x00000010, 0x00020000, 0x00100000, 0x00008000, 0x00000100, 0x00000800,
|
||||||
|
0x00000001, 0x00004000, 0x40000000, 0x00000002, 0x00800000, 0x80000000,
|
||||||
|
0x00010000, 0x00000020, 0x00000200, 0x00040000, 0x02000000, 0x00000004,
|
||||||
|
0x10000000, 0x00400000, 0x00002000, 0x08000000, 0x20000000, 0x01000000,
|
||||||
|
0x04000000, 0x00000400};
|
||||||
|
|
||||||
|
static uint32_t swapit(uint32_t val1)
|
||||||
|
{
|
||||||
|
int32_t i, shift;
|
||||||
|
uint32_t mask;
|
||||||
|
uint32_t val2;
|
||||||
|
|
||||||
|
val2 = 0;
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
mask = swapmask[i];
|
||||||
|
shift = swapshift[i];
|
||||||
|
if (shift >= 0)
|
||||||
|
val2 |= (val1 & mask) << shift;
|
||||||
|
else
|
||||||
|
val2 |= (val1 & mask) >> -shift;
|
||||||
|
}
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartPasmCog(PasmVarsT *pasmvars, int32_t par, int32_t addr, int32_t cogid)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
pasmvars->waitflag = 0;
|
||||||
|
pasmvars->cflag = 0;
|
||||||
|
pasmvars->zflag = 0;
|
||||||
|
pasmvars->pc = 0;
|
||||||
|
pasmvars->pc1 = 512;
|
||||||
|
pasmvars->pc2 = 512;
|
||||||
|
pasmvars->instruct1 = 0;
|
||||||
|
pasmvars->instruct2 = 0;
|
||||||
|
pasmvars->cogid = cogid;
|
||||||
|
pasmvars->state = 5;
|
||||||
|
pasmvars->mem[496] = par;
|
||||||
|
|
||||||
|
for (i = 0; i < 496; i++)
|
||||||
|
{
|
||||||
|
if (addr & 0x8000)
|
||||||
|
pasmvars->mem[i] = swapit(LONG(addr));
|
||||||
|
else
|
||||||
|
pasmvars->mem[i] = LONG(addr);
|
||||||
|
addr += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugPasmInstruction(PasmVarsT *pasmvars)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
int32_t cflag = pasmvars->cflag;
|
||||||
|
int32_t zflag = pasmvars->zflag;
|
||||||
|
int32_t instruct, cond, pc;
|
||||||
|
int32_t opcode, value2, value1, zcri;
|
||||||
|
int32_t srcaddr, dstaddr;
|
||||||
|
char *wzstr;
|
||||||
|
char *wcstr;
|
||||||
|
char *wrstr;
|
||||||
|
char *ptr;
|
||||||
|
char opstr[20];
|
||||||
|
char *istr[2] = {" ", "#"};
|
||||||
|
char *xstr[4] = {"X", " ", "W", "I"};
|
||||||
|
int32_t xflag;
|
||||||
|
|
||||||
|
// Fetch the instruction
|
||||||
|
if (pasmvars->waitflag)
|
||||||
|
{
|
||||||
|
pc = pasmvars->pc2;
|
||||||
|
instruct = pasmvars->instruct2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pc = pasmvars->pc1;
|
||||||
|
instruct = pasmvars->instruct1;
|
||||||
|
}
|
||||||
|
cond = (instruct >> 18) & 15;
|
||||||
|
xflag = ((cond >> ((cflag << 1) | zflag)) & 1);
|
||||||
|
|
||||||
|
// Check if the instruction is invalidated in the pipeline
|
||||||
|
if (pc & 0xfffffe00)
|
||||||
|
{
|
||||||
|
pc &= 0x1ff;
|
||||||
|
xflag = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract parameters from the instruction
|
||||||
|
opcode = (instruct >> 26) & 63;
|
||||||
|
srcaddr = instruct & 511;
|
||||||
|
dstaddr = (instruct >> 9) & 511;
|
||||||
|
zcri = (instruct >> 22) & 15;
|
||||||
|
|
||||||
|
// Get the two operands
|
||||||
|
value1 = pasmvars->mem[dstaddr];
|
||||||
|
if (zcri & 1)
|
||||||
|
value2 = srcaddr;
|
||||||
|
else
|
||||||
|
value2 = pasmvars->mem[srcaddr];
|
||||||
|
|
||||||
|
// Check for wait cycles for djnz, tjnz, tjz or hubop
|
||||||
|
if (cycleaccurate && xflag == 1)
|
||||||
|
{
|
||||||
|
if (opcode <= 0x07) // hubop
|
||||||
|
{
|
||||||
|
if (CheckWaitFlag(pasmvars, 3)) xflag = 2;
|
||||||
|
}
|
||||||
|
else if (opcode == 0x3e) // waitcnt
|
||||||
|
{
|
||||||
|
int32_t result = GetCnt() - value1;
|
||||||
|
if (result < 0 || result >= 4) xflag = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zcri&8) wzstr = " wz";
|
||||||
|
else wzstr = "";
|
||||||
|
if (zcri&4) wcstr = " wc";
|
||||||
|
else wcstr = "";
|
||||||
|
wrstr = "";
|
||||||
|
|
||||||
|
if (opcode == 3)
|
||||||
|
strcpy(opstr, hubops[value2 & 7][(zcri>>1)&1]);
|
||||||
|
else
|
||||||
|
strcpy(opstr, opnames[opcode][(zcri>>1)&1]);
|
||||||
|
ptr = FindChar(opstr, ' ');
|
||||||
|
if (*ptr)
|
||||||
|
{
|
||||||
|
*ptr++ = 0;
|
||||||
|
if (*ptr == 'w')
|
||||||
|
wrstr = " wr";
|
||||||
|
else if (*ptr == 'n')
|
||||||
|
wrstr = " nr";
|
||||||
|
}
|
||||||
|
|
||||||
|
i = strlen(opstr);
|
||||||
|
|
||||||
|
while (i < 7) opstr[i++] = ' ';
|
||||||
|
opstr[i] = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fprintf(tracefile, "%3.3x %8.8x %d %d %s %s %s %3.3x %s%3.3x %8.8x %8.8x", pasmvars->pc,
|
||||||
|
instruct, zflag, cflag, xstr[xflag], condnames[cond], opstr, dstaddr,
|
||||||
|
istr[zcri & 1], srcaddr, value1, value2);
|
||||||
|
#else
|
||||||
|
fprintf(tracefile, "%6d %3.3x %8.8x %s %s %s %3.3x, %s%3.3x%s%s%s", loopcount * 4, pc,
|
||||||
|
instruct, xstr[xflag], condnames[cond], opstr, dstaddr,
|
||||||
|
istr[zcri & 1], srcaddr, wzstr, wcstr, wrstr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,448 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.21
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "interp.h"
|
||||||
|
#include "spinsim.h"
|
||||||
|
|
||||||
|
#define REG_PINA 0x1f4
|
||||||
|
|
||||||
|
extern char *hubram;
|
||||||
|
extern int32_t memsize;
|
||||||
|
extern int32_t loopcount;
|
||||||
|
extern int32_t cycleaccurate;
|
||||||
|
extern int32_t pin_val;
|
||||||
|
|
||||||
|
extern FILE *tracefile;
|
||||||
|
|
||||||
|
static char *condnames[16] = {
|
||||||
|
"if_never ", "if_nz_and_nc", "if_z_and_nc ", "if_nc ",
|
||||||
|
"if_nz_and_c ", "if_nz ", "if_z_ne_c ", "if_nz_or_nc ",
|
||||||
|
"if_z_and_c ", "if_z_eq_c ", "if_z ", "if_z_or_nc ",
|
||||||
|
"if_c ", "if_nz_or_c ", "if_z_or_c ", " "};
|
||||||
|
|
||||||
|
char *opcodes_lower[64] = {
|
||||||
|
"rdbyte","rdbytec","rdword","rdwordc","rdlong","rdlongc","rdaux","rdauxr",
|
||||||
|
"isob","notb","clrb","setb","setbc","setbnc","setbz","setbnz",
|
||||||
|
"andn","and","or","xor","muxc","muxnc","muxz","muxnz",
|
||||||
|
"ror","rol","shr","shl","rcr","rcl","sar","rev",
|
||||||
|
"mov","not","abs","neg","negc","negnc","negz","negnz",
|
||||||
|
"add","sub","addx","subx","adds","subs","addsx","subsx",
|
||||||
|
"sumc","sumnc","sumz","sumnz","min","max","mins","maxs",
|
||||||
|
"addabs","subabs","incmod","decmod","cmpsub","subr","mul","scl"};
|
||||||
|
|
||||||
|
char *opcodes_upper[62][4] = {
|
||||||
|
{"decod2", "decod2", "decod2", "decod2"},
|
||||||
|
{"decod3", "decod3", "decod3", "decod3"},
|
||||||
|
{"decod4", "decod4", "decod4", "decod4"},
|
||||||
|
{"decod5", "decod5", "decod5", "decod5"},
|
||||||
|
{"encod", "blmask", "encod", "blmask"},
|
||||||
|
{"onecnt", "zercnt", "onecnt", "zercnt"},
|
||||||
|
{"incpat", "incpat", "decpat", "decpat"},
|
||||||
|
{"splitb", "mergeb", "splitw", "mergew"},
|
||||||
|
|
||||||
|
{"getnib", "setnib", "getnib", "setnib"},
|
||||||
|
{"getnib", "setnib", "getnib", "setnib"},
|
||||||
|
{"getnib", "setnib", "getnib", "setnib"},
|
||||||
|
{"getnib", "setnib", "getnib", "setnib"},
|
||||||
|
{"getword","setword","getword","setword"},
|
||||||
|
{"setwrds","rolnib", "rolbyte","rolword"},
|
||||||
|
{"sets", "setd", "setx", "seti"},
|
||||||
|
{"cognew", "cognew", "waitcnt","waitcnt"},
|
||||||
|
|
||||||
|
{"getbyte","setbyte","getbyte","setbyte"},
|
||||||
|
{"getbyte","setbyte","getbyte","setbyte"},
|
||||||
|
{"setbyts","movbyts","packrgb","unpkrgb"},
|
||||||
|
{"addpix", "mulpix", "blnpix", "mixpix"},
|
||||||
|
{"jmpsw", "jmpsw", "jmpsw", "jmpsw"},
|
||||||
|
{"jmpswd", "jmpswd", "jmpswd", "jmpswd"},
|
||||||
|
{"ijz", "ijzd", "ijnz", "ijnzd"},
|
||||||
|
{"djz", "djzd", "djnz", "djnzd"},
|
||||||
|
|
||||||
|
{"testb", "testb", "testb", "testb"},
|
||||||
|
{"testn", "testn", "testn", "testn"},
|
||||||
|
{"test", "test", "test", "test"},
|
||||||
|
{"cmp", "cmp", "cmp", "cmp"},
|
||||||
|
{"cmpx", "cmpx", "cmpx", "cmpx"},
|
||||||
|
{"cmps", "cmps", "cmps", "cmps"},
|
||||||
|
{"cmpsx", "cmpsx", "cmpsx", "cmpsx"},
|
||||||
|
{"cmpr", "cmpr", "cmpr", "cmpr"},
|
||||||
|
|
||||||
|
{"coginit","waitvid","coginit","waitvid"},
|
||||||
|
{"coginit","waitvid","coginit","waitvid"},
|
||||||
|
{"coginit","waitvid","coginit","waitvid"},
|
||||||
|
{"coginit","waitvid","coginit","waitvid"},
|
||||||
|
{"waitpeq","waitpeq","waitpeq","waitpeq"},
|
||||||
|
{"waitpeq","waitpeq","waitpeq","waitpeq"},
|
||||||
|
{"waitpne","waitpne","waitpne","waitpne"},
|
||||||
|
{"waitpne","waitpne","waitpne","waitpne"},
|
||||||
|
|
||||||
|
{"wrbyte", "wrbyte", "wrword", "wrword"},
|
||||||
|
{"wrlong", "wrlong", "frac", "frac"},
|
||||||
|
{"wraux", "wraux", "wrauxr", "wrauxr"},
|
||||||
|
{"setacca","setacca","setaccb","setaccb"},
|
||||||
|
{"maca", "maca", "macb", "macb"},
|
||||||
|
{"mul32", "mul32", "mul32u", "mul32u"},
|
||||||
|
{"div32", "div32", "div32u", "div32u"},
|
||||||
|
{"div64", "div64", "div64u", "div64u"},
|
||||||
|
|
||||||
|
{"sqrt64", "sqrt64", "qsincos","qsincos"},
|
||||||
|
{"qarctan","qarctan","qrotate","qrotate"},
|
||||||
|
{"setsera","setsera","setserb","setserb"},
|
||||||
|
{"setctrs","setctrs","setwavs","setwavs"},
|
||||||
|
{"setfrqs","setfrqs","setphss","setphss"},
|
||||||
|
{"addphss","addphss","subphss","subphss"},
|
||||||
|
{"jp", "jp", "jpd", "jpd"},
|
||||||
|
{"jnp", "jnp", "jnpd", "jnpd"},
|
||||||
|
|
||||||
|
{"cfgpins","cfgpins","cfgpins","cfgpins"},
|
||||||
|
{"cfgpins","cfgpins","jmptask","jmptask"},
|
||||||
|
{"setxfr", "setxfr", "setmix", "setmix"},
|
||||||
|
{"jz", "jzd", "jnz", "jnzd"},
|
||||||
|
{"locbase","locbyte","locword","loclong"},
|
||||||
|
{"jmplist","locinst","augs", "augd"}};
|
||||||
|
|
||||||
|
int zci_upper[62][4] = {
|
||||||
|
{7, 7, 7, 7}, {7, 7, 7, 7}, {7, 7, 7, 7}, {7, 7, 7, 7},
|
||||||
|
{5, 5, 5, 5}, {5, 5, 5, 5}, {3, 3, 3, 3}, {1, 1, 1, 1},
|
||||||
|
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {3, 3, 3, 3},
|
||||||
|
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
{7, 7, 7, 7}, {7, 7, 7, 7}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
|
||||||
|
{7, 7, 7, 7}, {7, 7, 7, 7}, {7, 7, 7, 7}, {7, 7, 7, 7},
|
||||||
|
{7, 7, 7, 7}, {7, 7, 7, 7}, {7, 7, 7, 7}, {7, 7, 7, 7},
|
||||||
|
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
{3, 3, 3, 3}, {3, 3, 3, 3}, {3, 3, 3, 3}, {3, 3, 3, 3},
|
||||||
|
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||||
|
|
||||||
|
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
|
||||||
|
|
||||||
|
char *opcodes_ind[16] = {
|
||||||
|
"invalid", "fixinda", "setinda", "setinda",
|
||||||
|
"fixindb", "fixinds", "invalid", "invalid",
|
||||||
|
"setindb", "invalid", "setinds", "setinds",
|
||||||
|
"setindb", "invalid", "setinds", "setinds"};
|
||||||
|
|
||||||
|
char *opcodes_16[14] = {
|
||||||
|
"locptra","locptrb","jmp","jmpd","call","calld","calla",
|
||||||
|
"callad","callb","callbd","callx","callxd","cally","callyd"};
|
||||||
|
|
||||||
|
char *opcodes_set1[49] = {
|
||||||
|
"cogid","taskid","locknew","getlfsr","getcnt","getcntx","getacal","getacah",
|
||||||
|
"getacbl","getacbh","getptra","getptrb","getptrx","getptry","serina","serinb",
|
||||||
|
"getmull","getmulh","getdivq","getdivr","getsqrt","getqx","getqy","getqz",
|
||||||
|
"getphsa","getphza","getcosa","getsina","getphsb","getphzb","getcosb","getsinb",
|
||||||
|
"pushzc","popzc","subcnt","getpix","binbcd","bcdbin","bingry","grybin",
|
||||||
|
"eswap4","eswap8","seussf","seussr","incd","decd","incds","decds","pop"};
|
||||||
|
|
||||||
|
char *opcodes_set2[] = {
|
||||||
|
"clkset", "cogstop", "lockset", "lockclr", "lockret", "rdwidec", "rdwide",
|
||||||
|
"wrwide", "getp", "getnp", "serouta", "seroutb", "cmpcnt", "waitpx",
|
||||||
|
"waitpr", "waitpf", "setzc", "setmap", "setxch", "settask", "setrace",
|
||||||
|
"saracca", "saraccb", "saraccs", "setptra", "setptrb", "addptra", "addptrb",
|
||||||
|
"subptra", "subptrb", "setwide", "setwidz", "setptrx", "setptry",
|
||||||
|
"addptrx", "addptry", "subptrx", "subptry", "passcnt", "wait", "offp",
|
||||||
|
"notp", "clrp", "setp", "setpc", "setpnc", "setpz", "stpnz", "div64d",
|
||||||
|
"sqrt32", "qlog", "qexp", "setqi", "setqz", "cfgdacs", "setdacs",
|
||||||
|
"cfgdac0", "cfgdac1", "cfgdac2", "cfgdac3", "setdac0", "setdac1",
|
||||||
|
"setdac2", "seddac3", "setctra", "setwava", "setfrqa", "setphsa",
|
||||||
|
"addphsa", "subphsa", "setvid", "setvidy", "setctrb", "setwavb", "setfrqb",
|
||||||
|
"setphsb", "addphsb", "subphsb", "setvidi", "setvidq", "setpix", "setpixz",
|
||||||
|
"setpixu", "setpixv", "setpixa", "setpixr", "setpixg", "setpixb",
|
||||||
|
"setpora", "setporb", "setporc", "setpord", "push"};
|
||||||
|
|
||||||
|
char *opcodes_set3[40] = {
|
||||||
|
"jmp", "jmpd", "call", "calld", "calla", "callad", "callb", "callbd",
|
||||||
|
"callx", "callxd", "cally", "callyd", "reta", "retad", "retb", "retbd",
|
||||||
|
"retx", "retxd", "rety", "retyd", "ret", "retd", "polctra", "polctrb",
|
||||||
|
"polvid", "capctra", "capctrb", "capctrs", "setpixw", "clracca", "clraccb",
|
||||||
|
"clraccs", "chkptrx", "chkptry", "syntra", "synctrb", "dcachex", "icachex",
|
||||||
|
"icachep", "icachen"};
|
||||||
|
|
||||||
|
int zci_set3[40] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
|
||||||
|
char *GetOpname2(unsigned int instr, int *pzci)
|
||||||
|
{
|
||||||
|
int opcode = instr >> 25;
|
||||||
|
int zci = (instr >> 22) & 7;
|
||||||
|
int cond = (instr >> 18) & 15;
|
||||||
|
int src = instr & 0x1ff;
|
||||||
|
int dst = (instr >> 9) & 0x1ff;
|
||||||
|
int zc = zci >> 1;
|
||||||
|
|
||||||
|
//printf("opcode = $%2.2x, zci = %d\n", opcode, zci);
|
||||||
|
|
||||||
|
if (opcode < 64)
|
||||||
|
{
|
||||||
|
*pzci = 7;
|
||||||
|
return opcodes_lower[opcode];
|
||||||
|
}
|
||||||
|
else if(opcode < 126)
|
||||||
|
{
|
||||||
|
*pzci = zci_upper[opcode-64][zc];
|
||||||
|
return opcodes_upper[opcode-64][zc];
|
||||||
|
}
|
||||||
|
else if (opcode == 126 && zci == 0)
|
||||||
|
{
|
||||||
|
*pzci = 0;
|
||||||
|
return opcodes_ind[cond];
|
||||||
|
}
|
||||||
|
else if (opcode == 126)
|
||||||
|
{
|
||||||
|
*pzci = 0;
|
||||||
|
return opcodes_16[(zci-1)*2 + (dst >> 8)];
|
||||||
|
}
|
||||||
|
else if (src <= 48)
|
||||||
|
{
|
||||||
|
if (src < 44 || src == 48)
|
||||||
|
*pzci = 7;
|
||||||
|
else
|
||||||
|
*pzci = 5;
|
||||||
|
return opcodes_set1[src];
|
||||||
|
}
|
||||||
|
if (src < 64)
|
||||||
|
{
|
||||||
|
*pzci = 0;
|
||||||
|
return "invalid";
|
||||||
|
}
|
||||||
|
if (src < 128)
|
||||||
|
{
|
||||||
|
*pzci = 1;
|
||||||
|
return "repd";
|
||||||
|
}
|
||||||
|
if (src < 220)
|
||||||
|
{
|
||||||
|
if (src == 136 || src == 137 || src == 144)
|
||||||
|
*pzci = 7;
|
||||||
|
else if (src == 130 || src == 131)
|
||||||
|
*pzci = 3;
|
||||||
|
else
|
||||||
|
*pzci = 1;
|
||||||
|
return opcodes_set2[src-128];
|
||||||
|
}
|
||||||
|
if (src < 0xf4)
|
||||||
|
{
|
||||||
|
*pzci = 0;
|
||||||
|
return "invalid";
|
||||||
|
}
|
||||||
|
if (src <= 0x11b)
|
||||||
|
{
|
||||||
|
*pzci = zci_set3[src-0xf4];
|
||||||
|
return opcodes_set3[src-0xf4];
|
||||||
|
}
|
||||||
|
*pzci = 0;
|
||||||
|
return "invalid";
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartPasmCog2(PasmVarsT *pasmvars, int32_t par, int32_t addr, int32_t cogid)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
// printf("\nStartPasmCog2: %8.8x, %8.8x, %d\n", par, addr, cogid);
|
||||||
|
par &= 0x3ffff;
|
||||||
|
addr &= 0x3fffc;
|
||||||
|
pasmvars->waitflag = 0;
|
||||||
|
pasmvars->cflag = 0;
|
||||||
|
pasmvars->zflag = 0;
|
||||||
|
pasmvars->pc = 0;
|
||||||
|
pasmvars->cogid = cogid;
|
||||||
|
pasmvars->state = 5;
|
||||||
|
pasmvars->ptra = par;
|
||||||
|
pasmvars->ptrb = addr;
|
||||||
|
pasmvars->ptrx = 0;
|
||||||
|
pasmvars->ptry = 0;
|
||||||
|
pasmvars->inda = 0x1f2;
|
||||||
|
pasmvars->indatop = 0;
|
||||||
|
pasmvars->indabot = 0;
|
||||||
|
pasmvars->indb = 0x1f3;
|
||||||
|
pasmvars->indbtop = 0;
|
||||||
|
pasmvars->indbbot = 0;
|
||||||
|
pasmvars->repcnt = 0;
|
||||||
|
pasmvars->repbot = 0;
|
||||||
|
pasmvars->reptop = 0;
|
||||||
|
pasmvars->repforever = 0;
|
||||||
|
pasmvars->dcachehubaddr = 0xffffffff;
|
||||||
|
pasmvars->dcachecogaddr = 0xffffffff;
|
||||||
|
pasmvars->instruct1 = 0;
|
||||||
|
pasmvars->instruct2 = 0;
|
||||||
|
pasmvars->instruct3 = 0;
|
||||||
|
pasmvars->instruct4 = 0;
|
||||||
|
pasmvars->pc1 = INVALIDATE_INSTR;
|
||||||
|
pasmvars->pc2 = INVALIDATE_INSTR;
|
||||||
|
pasmvars->pc3 = INVALIDATE_INSTR;
|
||||||
|
pasmvars->pc4 = INVALIDATE_INSTR;
|
||||||
|
pasmvars->retptr = 0;
|
||||||
|
pasmvars->acca = 0;
|
||||||
|
pasmvars->accb = 0;
|
||||||
|
pasmvars->mulcount = 0;
|
||||||
|
pasmvars->breakpnt = -1;
|
||||||
|
pasmvars->augsflag = 0;
|
||||||
|
pasmvars->augsvalue = 0;
|
||||||
|
pasmvars->augdflag = 0;
|
||||||
|
pasmvars->augdvalue = 0;
|
||||||
|
pasmvars->icachehubaddr[0] = 0xffffffff;
|
||||||
|
pasmvars->icachehubaddr[1] = 0xffffffff;
|
||||||
|
pasmvars->icachehubaddr[2] = 0xffffffff;
|
||||||
|
pasmvars->icachehubaddr[3] = 0xffffffff;
|
||||||
|
pasmvars->icachenotused[0] = 0;
|
||||||
|
pasmvars->icachenotused[1] = 0;
|
||||||
|
pasmvars->icachenotused[2] = 0;
|
||||||
|
pasmvars->icachenotused[3] = 0;
|
||||||
|
pasmvars->prefetch = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < 0x1f4; i++)
|
||||||
|
{
|
||||||
|
pasmvars->mem[i] = LONG(addr);
|
||||||
|
addr += 4;
|
||||||
|
}
|
||||||
|
for (i = 0x1f4; i < 512; i++) pasmvars->mem[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugPasmInstruction2(PasmVarsT *pasmvars)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
int32_t cflag = pasmvars->cflag;
|
||||||
|
int32_t zflag = pasmvars->zflag;
|
||||||
|
int32_t instruct, pc, cond, xflag;
|
||||||
|
int32_t opcode, zci;
|
||||||
|
int32_t srcaddr, dstaddr;
|
||||||
|
char *wzstr = "";
|
||||||
|
char *wcstr = "";
|
||||||
|
char opstr[20];
|
||||||
|
char *istr[3] = {" ", "#", "@"};
|
||||||
|
char *xstr[8] = {" ", "X", "I", "H", "C", "P", "W", "?"};
|
||||||
|
int zci_mask;
|
||||||
|
int32_t sflag, dflag, indirect, opcode_zci;
|
||||||
|
|
||||||
|
// Fetch the instruction
|
||||||
|
pc = pasmvars->pc4;
|
||||||
|
instruct = pasmvars->instruct4;
|
||||||
|
cond = (instruct >> 18) & 15;
|
||||||
|
|
||||||
|
// Extract parameters from the instruction
|
||||||
|
opcode = (instruct >> 25) & 127;
|
||||||
|
srcaddr = instruct & 511;
|
||||||
|
dstaddr = (instruct >> 9) & 511;
|
||||||
|
zci = (instruct >> 22) & 7;
|
||||||
|
opcode_zci = (opcode << 3) | zci;
|
||||||
|
|
||||||
|
// Decode the immediate flags for the source and destination fields
|
||||||
|
sflag = (opcode_zci >= 0x3ea) | (zci & 1);
|
||||||
|
|
||||||
|
dflag = (opcode >= 0x68 && opcode <= 0x7a && (zci & 2)) |
|
||||||
|
(opcode_zci >= 0x302 && opcode_zci <= 0x31f) |
|
||||||
|
(opcode != 0x7f && opcode_zci >= 0x3eb) |
|
||||||
|
(opcode == 0x7f && srcaddr >= 0x40 && srcaddr <= 0xdc && (zci & 1)) |
|
||||||
|
(opcode == 0x7f && srcaddr >= 0x100);
|
||||||
|
|
||||||
|
// Determine if indirect registers are used
|
||||||
|
indirect = (!sflag && (srcaddr & 0x1fe) == 0x1f2) |
|
||||||
|
(!dflag && (dstaddr & 0x1fe) == 0x1f2) |
|
||||||
|
(opcode_zci == 0x3f0);
|
||||||
|
|
||||||
|
if (indirect) cond = 0xf;
|
||||||
|
xflag = ((cond >> ((cflag << 1) | zflag)) & 1);
|
||||||
|
xflag ^= 1;
|
||||||
|
|
||||||
|
// Check if the instruction is invalidated in the pipeline
|
||||||
|
if (pc & INVALIDATE_INSTR)
|
||||||
|
{
|
||||||
|
pc &= ~INVALIDATE_INSTR;
|
||||||
|
xflag = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pasmvars->waitflag && pasmvars->waitmode == WAIT_CACHE) xflag = 4;
|
||||||
|
else if (xflag == 4) xflag = 5;
|
||||||
|
|
||||||
|
if (pasmvars->waitflag)
|
||||||
|
{
|
||||||
|
if (pasmvars->waitmode == WAIT_CACHE)
|
||||||
|
xflag = 4;
|
||||||
|
else if (pasmvars->waitmode == WAIT_CNT)
|
||||||
|
xflag = 6;
|
||||||
|
else if (pasmvars->waitmode == WAIT_PIN)
|
||||||
|
xflag = 5;
|
||||||
|
else if (pasmvars->waitmode == WAIT_HUB)
|
||||||
|
xflag = 3;
|
||||||
|
else
|
||||||
|
xflag = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(opstr, GetOpname2(instruct, &zci_mask));
|
||||||
|
|
||||||
|
zci &= zci_mask;
|
||||||
|
if (zci & 4) wzstr = " wz";
|
||||||
|
if (zci & 2) wcstr = " wc";
|
||||||
|
|
||||||
|
i = strlen(opstr);
|
||||||
|
while (i < 7) opstr[i++] = ' ';
|
||||||
|
opstr[i] = 0;
|
||||||
|
|
||||||
|
// Check for NOP
|
||||||
|
if (!instruct)
|
||||||
|
{
|
||||||
|
cond = 15;
|
||||||
|
if (xflag == 1) xflag = 0;
|
||||||
|
strcpy(opstr, "nop ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for REPS
|
||||||
|
if ((instruct & 0xffc00000) == 0xfac00000)
|
||||||
|
{
|
||||||
|
cond = 15;
|
||||||
|
if (xflag == 1) xflag = 0;
|
||||||
|
strcpy(opstr, "reps ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for AUGS or AUGD
|
||||||
|
if (opcode_zci >= 0x3ec && opcode_zci <= 0x3ef)
|
||||||
|
{
|
||||||
|
cond = 15;
|
||||||
|
if (xflag == 1) xflag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pasmvars->printflag - 2 < xflag && xflag != 0)
|
||||||
|
{
|
||||||
|
pasmvars->printflag = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(tracefile, "Cog %d: %8.8x ", pasmvars->cogid, loopcount);
|
||||||
|
fprintf(tracefile, "%4.4x %8.8x %s %s %s %s%3.3x, %s%3.3x%s%s", pc,
|
||||||
|
instruct, xstr[xflag], condnames[cond], opstr, istr[dflag], dstaddr,
|
||||||
|
istr[sflag], srcaddr, wzstr, wcstr);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,742 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.21
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "interp.h"
|
||||||
|
|
||||||
|
extern char *hubram;
|
||||||
|
extern int32_t memsize;
|
||||||
|
extern char lockstate[8];
|
||||||
|
extern char lockalloc[8];
|
||||||
|
extern PasmVarsT PasmVars[8];
|
||||||
|
extern int32_t pasmspin;
|
||||||
|
extern int32_t cycleaccurate;
|
||||||
|
extern int32_t loopcount;
|
||||||
|
extern int32_t proptwo;
|
||||||
|
extern int32_t pin_val;
|
||||||
|
|
||||||
|
extern FILE *tracefile;
|
||||||
|
|
||||||
|
void PrintResults(int32_t zcri, int32_t zflag, int32_t cflag, int32_t result)
|
||||||
|
{
|
||||||
|
if (zcri & 8) printf(" Z=%d", zflag);
|
||||||
|
if (zcri & 4) printf(" C=%d", cflag);
|
||||||
|
if (zcri & 2) printf(" R=%8.8x", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t parity(int32_t val)
|
||||||
|
{
|
||||||
|
val ^= val >> 16;
|
||||||
|
val ^= val >> 8;
|
||||||
|
val ^= val >> 4;
|
||||||
|
val ^= val >> 2;
|
||||||
|
val ^= val >> 1;
|
||||||
|
return val & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t abs(int32_t val)
|
||||||
|
{
|
||||||
|
return val < 0 ? -val : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CheckWaitFlag(PasmVarsT *pasmvars, int mode)
|
||||||
|
{
|
||||||
|
int32_t hubmode = mode & 1;
|
||||||
|
int32_t debugmode = mode & 2;
|
||||||
|
int32_t waitflag = pasmvars->waitflag;
|
||||||
|
|
||||||
|
if (waitflag)
|
||||||
|
{
|
||||||
|
waitflag--;
|
||||||
|
}
|
||||||
|
else if (hubmode)
|
||||||
|
{
|
||||||
|
if (proptwo)
|
||||||
|
waitflag = (pasmvars->cogid - loopcount) & 7;
|
||||||
|
else
|
||||||
|
waitflag = ((pasmvars->cogid >> 1) - loopcount) & 3;
|
||||||
|
waitflag++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (proptwo)
|
||||||
|
waitflag = 2;
|
||||||
|
else
|
||||||
|
waitflag = 1;
|
||||||
|
}
|
||||||
|
if (!debugmode)
|
||||||
|
{
|
||||||
|
//if (waitflag)
|
||||||
|
//pasmvars->pc = (pasmvars->pc - 1) & 511;
|
||||||
|
pasmvars->waitflag = waitflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return waitflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdjustPipeForJump(PasmVarsT *pasmvars, int32_t value, int32_t jump)
|
||||||
|
{
|
||||||
|
int32_t pc = value & 0x1ff;
|
||||||
|
pasmvars->instruct1 = pasmvars->mem[pc];
|
||||||
|
if (jump)
|
||||||
|
{
|
||||||
|
pasmvars->pc = (pc + 1) & 511;
|
||||||
|
pasmvars->pc1 = pc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pasmvars->pc = pasmvars->pc1;
|
||||||
|
pasmvars->pc1 = pc | 512;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ExecutePasmInstruction(PasmVarsT *pasmvars)
|
||||||
|
{
|
||||||
|
int32_t cflag = pasmvars->cflag;
|
||||||
|
int32_t zflag = pasmvars->zflag;
|
||||||
|
int32_t instruct, cond, pc;
|
||||||
|
int32_t opcode, value2, value1, zcri;
|
||||||
|
int32_t srcaddr, dstaddr;
|
||||||
|
int32_t result = 0;
|
||||||
|
|
||||||
|
// Fetch a new instruction and update the pipeline
|
||||||
|
if (!pasmvars->waitflag)
|
||||||
|
{
|
||||||
|
//printf("Fetch new instruction\n");
|
||||||
|
pasmvars->instruct2 = pasmvars->instruct1;
|
||||||
|
pasmvars->instruct1 = pasmvars->mem[pasmvars->pc];
|
||||||
|
pasmvars->pc2 = pasmvars->pc1;
|
||||||
|
pasmvars->pc1 = pasmvars->pc;
|
||||||
|
pasmvars->pc = (pasmvars->pc + 1) & 511;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the instruction and pc at the end of the pipeline
|
||||||
|
instruct = pasmvars->instruct2;
|
||||||
|
pc = pasmvars->pc2;
|
||||||
|
cond = (instruct >> 18) & 15;
|
||||||
|
|
||||||
|
// Return if not executed
|
||||||
|
if ((!((cond >> ((cflag << 1) | zflag)) & 1)) || (pc & 0xfffffe00))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a hub wait
|
||||||
|
if (cycleaccurate && !(instruct & 0xe0000000))
|
||||||
|
{
|
||||||
|
if (CheckWaitFlag(pasmvars, 1)) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract parameters from the instruction
|
||||||
|
opcode = (instruct >> 26) & 63;
|
||||||
|
srcaddr = instruct & 511;
|
||||||
|
dstaddr = (instruct >> 9) & 511;
|
||||||
|
zcri = (instruct >> 22) & 15;
|
||||||
|
|
||||||
|
// Get the two operands
|
||||||
|
value1 = pasmvars->mem[dstaddr];
|
||||||
|
if (zcri & 1)
|
||||||
|
value2 = srcaddr;
|
||||||
|
else if (srcaddr == 0x1f1)
|
||||||
|
value2 = GetCnt();
|
||||||
|
else if (srcaddr == 0x1f2)
|
||||||
|
value2 = pin_val;
|
||||||
|
else
|
||||||
|
value2 = pasmvars->mem[srcaddr];
|
||||||
|
|
||||||
|
// Decode the three most significant bits of the opcode
|
||||||
|
switch(opcode >> 3)
|
||||||
|
{
|
||||||
|
// Hub access opcodes
|
||||||
|
case 0:
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // wrbyte, rdbyte
|
||||||
|
case 1: // wrword, rdword
|
||||||
|
case 2: // wrlong, rdlong
|
||||||
|
if (zcri & 2) // read
|
||||||
|
{
|
||||||
|
if ((opcode & 7) == 0)
|
||||||
|
result = BYTE(value2);
|
||||||
|
else if ((opcode & 7) == 1)
|
||||||
|
result = WORD(value2);
|
||||||
|
else
|
||||||
|
result = LONG(value2);
|
||||||
|
zflag = (result == 0);
|
||||||
|
}
|
||||||
|
else // write
|
||||||
|
{
|
||||||
|
if ((opcode & 7) == 0)
|
||||||
|
BYTE(value2) = pasmvars->mem[dstaddr];
|
||||||
|
else if ((opcode & 7) == 1)
|
||||||
|
WORD(value2) = pasmvars->mem[dstaddr];
|
||||||
|
else
|
||||||
|
LONG(value2) = pasmvars->mem[dstaddr];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // misc hubops
|
||||||
|
switch (value2 & 7)
|
||||||
|
{
|
||||||
|
int32_t par, addr;
|
||||||
|
case 0: // clkset
|
||||||
|
result = value1 & 0xff;
|
||||||
|
if (result & 0x80)
|
||||||
|
{
|
||||||
|
RebootProp();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // cogid
|
||||||
|
result = pasmvars->cogid;
|
||||||
|
//pasmvars->mem[dstaddr] = result;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // coginit
|
||||||
|
par = (value1 >> 16) & 0xfffc;
|
||||||
|
addr = (value1 >> 2) & 0xfffc;
|
||||||
|
if (value1 & 8) // Start new cog
|
||||||
|
{
|
||||||
|
// Look for next available cog
|
||||||
|
for (result = 0; result < 8; result++)
|
||||||
|
{
|
||||||
|
if (!PasmVars[result].state) break;
|
||||||
|
}
|
||||||
|
if (result == 8) // Check if none available
|
||||||
|
{
|
||||||
|
cflag = 1;
|
||||||
|
result = 7;
|
||||||
|
zflag = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = value1 & 7;
|
||||||
|
}
|
||||||
|
cflag = 0;
|
||||||
|
zflag = (result == 0);
|
||||||
|
if (addr == 0xf004 && !pasmspin)
|
||||||
|
{
|
||||||
|
SpinVarsT *spinvars = (SpinVarsT *)&PasmVars[result].mem[0x1e0];
|
||||||
|
StartCog(spinvars, par, result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartPasmCog(&PasmVars[result], par, addr, result);
|
||||||
|
}
|
||||||
|
UpdatePins();
|
||||||
|
// Return without saving if we restarted this cog
|
||||||
|
if (result == pasmvars->cogid) return result;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // cogstop
|
||||||
|
for (result = 0; result < 8; result++)
|
||||||
|
{
|
||||||
|
if (!PasmVars[result].state) break;
|
||||||
|
}
|
||||||
|
cflag = (result == 8);
|
||||||
|
result = value1 & 7;
|
||||||
|
zflag = (result == 0);
|
||||||
|
PasmVars[result].state = 0;
|
||||||
|
UpdatePins();
|
||||||
|
// Return without saving if we stopped this cog
|
||||||
|
if (result == pasmvars->cogid) return result;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // locknew
|
||||||
|
for (result = 0; result < 8; result++)
|
||||||
|
{
|
||||||
|
if (!lockalloc[result]) break;
|
||||||
|
}
|
||||||
|
if (result == 8)
|
||||||
|
{
|
||||||
|
cflag = 1;
|
||||||
|
result = 7;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cflag = 0;
|
||||||
|
lockalloc[result] = 1;
|
||||||
|
}
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // lockret
|
||||||
|
for (result = 0; result < 8; result++)
|
||||||
|
{
|
||||||
|
if (!lockalloc[result]) break;
|
||||||
|
}
|
||||||
|
cflag = (result == 8);
|
||||||
|
result = value1 & 7;
|
||||||
|
zflag = (result == 0);
|
||||||
|
lockalloc[result] = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // lockset
|
||||||
|
result = value1 & 7;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = lockstate[result] & 1;
|
||||||
|
lockstate[result] = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // lockclr
|
||||||
|
result = value1 & 7;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = lockstate[result] & 1;
|
||||||
|
lockstate[result] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // Not defined
|
||||||
|
//printf("Undefined op - %8.8x\n", instruct);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Rotate and shift
|
||||||
|
case 1:
|
||||||
|
value2 &= 0x1f; // Get five LSB's
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // ror
|
||||||
|
result = (((uint32_t)value1) >> value2) | (value1 << (32 - value2));
|
||||||
|
cflag = value1 & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // rol
|
||||||
|
result = (((uint32_t)value1) >> (32 - value2)) | (value1 << value2);
|
||||||
|
cflag = (value1 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // shr
|
||||||
|
result = (((uint32_t)value1) >> value2);
|
||||||
|
cflag = value1 & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // shl
|
||||||
|
result = (value1 << value2);
|
||||||
|
cflag = (value1 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // rcr
|
||||||
|
if (value2)
|
||||||
|
{
|
||||||
|
result = (cflag << 31) | (((uint32_t)value1) >> 1);
|
||||||
|
result >>= (value2 - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = value1;
|
||||||
|
cflag = value1 & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // rcl
|
||||||
|
result = cflag ? (1 << value2) - 1 : 0;
|
||||||
|
result |= (value1 << value2);
|
||||||
|
cflag = (value1 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // sar
|
||||||
|
result = value1 >> value2;
|
||||||
|
cflag = value1 & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // rev
|
||||||
|
cflag = value1 & 1;
|
||||||
|
value2 = 32 - value2;
|
||||||
|
result = 0;
|
||||||
|
while (value2-- > 0)
|
||||||
|
{
|
||||||
|
result = (result << 1) | (value1 & 1);
|
||||||
|
value1 >>= 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Jump, call, return and misc.
|
||||||
|
case 2:
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // mins
|
||||||
|
cflag = (value1 < value2);
|
||||||
|
zflag = (value2 == 0);
|
||||||
|
result = cflag ? value2 : value1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // maxs
|
||||||
|
cflag = (value1 < value2);
|
||||||
|
zflag = (value2 == 0);
|
||||||
|
result = cflag ? value1 : value2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // min
|
||||||
|
cflag = (((uint32_t)value1) < ((uint32_t)value2));
|
||||||
|
zflag = (value2 == 0);
|
||||||
|
result = cflag ? value2 : value1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // max
|
||||||
|
cflag = (((uint32_t)value1) < ((uint32_t)value2));
|
||||||
|
zflag = (value2 == 0);
|
||||||
|
result = cflag ? value1 : value2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // movs
|
||||||
|
cflag = ((uint32_t)value1) < ((uint32_t)value2);
|
||||||
|
result = (value1 & 0xfffffe00) | (value2 &0x1ff);
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // movd
|
||||||
|
cflag = ((uint32_t)value1) < ((uint32_t)value2);
|
||||||
|
result = (value1 & 0xfffc01ff) | ((value2 &0x1ff) << 9);
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // movi
|
||||||
|
cflag = ((uint32_t)value1) < ((uint32_t)value2);
|
||||||
|
result = (value1 & 0x007fffff) | ((value2 &0x1ff) << 23);
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // ret, jmp, call, jmpret
|
||||||
|
cflag = ((uint32_t)value1) < ((uint32_t)value2);
|
||||||
|
result = (value1 & 0xfffffe00) | ((pc + 1) & 0x1ff);
|
||||||
|
//pasmvars->pc = value2 & 0x1ff;
|
||||||
|
AdjustPipeForJump(pasmvars, value2, 1);
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Logical operations
|
||||||
|
case 3:
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // test, and
|
||||||
|
result = value1 & value2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // testn, andn
|
||||||
|
result = value1 & (~value2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // or
|
||||||
|
result = value1 | value2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // xor
|
||||||
|
result = value1 ^ value2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // muxc
|
||||||
|
result = (value1 & (~value2)) | (value2 & (-cflag));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // muxnc
|
||||||
|
result = (value1 & (~value2)) | (value2 & (~(-cflag)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // muxz
|
||||||
|
result = (value1 & (~value2)) | (value2 & (-zflag));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // muxnz
|
||||||
|
result = (value1 & (~value2)) | (value2 & (~(-zflag)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = parity(result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Add and subtract
|
||||||
|
case 4:
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // add
|
||||||
|
result = value1 + value2;
|
||||||
|
cflag = (((value1 & value2) | ((value1 | value2) & (~result))) >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // cmp, sub
|
||||||
|
result = value1 - value2;
|
||||||
|
cflag = ((uint32_t)value1) < ((uint32_t)value2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // addabs
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
value2 = abs(value2);
|
||||||
|
result = value1 + value2;
|
||||||
|
cflag ^= (((value1 & value2) | ((value1 | value2) & (~result))) >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // subabs
|
||||||
|
result = abs(value2);
|
||||||
|
cflag = ((value2 >> 31) & 1) ^
|
||||||
|
(((uint32_t)value1) < ((uint32_t)result));
|
||||||
|
result = value1 - result;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // sumc
|
||||||
|
result = cflag ? value1 - value2 : value1 + value2;
|
||||||
|
cflag = (~cflag) << 31;
|
||||||
|
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // sumnc
|
||||||
|
result = cflag ? value1 + value2 : value1 - value2;
|
||||||
|
cflag = cflag << 31;
|
||||||
|
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // sumz
|
||||||
|
result = zflag ? value1 - value2 : value1 + value2;
|
||||||
|
cflag = (~zflag) << 31;
|
||||||
|
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // sumnz
|
||||||
|
result = zflag ? value1 + value2 : value1 - value2;
|
||||||
|
cflag = zflag << 31;
|
||||||
|
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Move, absolute and negate
|
||||||
|
case 5:
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // mov
|
||||||
|
result = value2;
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // neg
|
||||||
|
cflag = value2 < 0;
|
||||||
|
result = -value2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // abs
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
result = abs(value2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // absneg
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
result = -abs(value2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // negc
|
||||||
|
result = cflag ? -value2 : value2;
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // negnc
|
||||||
|
result = cflag ? value2 : -value2;
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // negz
|
||||||
|
result = zflag ? -value2 : value2;
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // negnz
|
||||||
|
result = zflag ? value2 : -value2;
|
||||||
|
cflag = (value2 >> 31) & 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// More add and subtract
|
||||||
|
case 6:
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // cmps
|
||||||
|
result = value1 - value2;
|
||||||
|
cflag = value1 < value2;
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // cmpsx
|
||||||
|
result = value1 - value2 - cflag;
|
||||||
|
cflag = value1 < (value2 + cflag);
|
||||||
|
zflag = (result == 0) & zflag;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // addx
|
||||||
|
result = value1 + value2 + cflag;
|
||||||
|
cflag = (((value1 & value2) | ((value1 | value2) & (~result))) >> 31) & 1;
|
||||||
|
zflag = (result == 0) & zflag;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // cmpx, subx
|
||||||
|
result = value1 - value2 - cflag;
|
||||||
|
if (value2 != 0xffffffff || !cflag)
|
||||||
|
cflag = ((uint32_t)value1) < ((uint32_t)(value2 + cflag));
|
||||||
|
zflag = (result == 0) & zflag;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // adds
|
||||||
|
result = value1 + value2;
|
||||||
|
cflag = (((~(value1 ^ value2)) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // subs
|
||||||
|
result = value1 - value2;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = (((value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // addsx
|
||||||
|
result = value1 + value2 + cflag;
|
||||||
|
cflag = (((~(value1 ^ value2)) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
zflag = (result == 0) & zflag;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // subsx
|
||||||
|
result = value1 - value2 - cflag;
|
||||||
|
cflag = (((value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
|
||||||
|
zflag = (result == 0) & zflag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Test and jump and wait ops
|
||||||
|
case 7:
|
||||||
|
switch (opcode & 7)
|
||||||
|
{
|
||||||
|
case 0: // cmpsub
|
||||||
|
cflag = (((uint32_t)value1) >= ((uint32_t)value2));
|
||||||
|
result = cflag ? value1 - value2 : value1;
|
||||||
|
zflag = (result == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // djnz
|
||||||
|
result = value1 - 1;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = (result == -1);
|
||||||
|
AdjustPipeForJump(pasmvars, value2, !zflag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // tjnz
|
||||||
|
result = value1;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = 0;
|
||||||
|
AdjustPipeForJump(pasmvars, value2, !zflag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // tjz
|
||||||
|
result = value1;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = 0;
|
||||||
|
AdjustPipeForJump(pasmvars, value2, zflag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // waitpeq - result, zflag and cflag not validated
|
||||||
|
result = (pin_val & value2) ^ value1;
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
//pasmvars->state = 6;
|
||||||
|
//pasmvars->pc = (pasmvars->pc - 1) & 511;
|
||||||
|
pasmvars->waitflag = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//pasmvars->state = 5;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // waitpne - result, zflag and cflag not validated
|
||||||
|
result = (pin_val & value2) ^ value1;
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
//pasmvars->state = 6;
|
||||||
|
//pasmvars->pc = (pasmvars->pc - 1) & 511;
|
||||||
|
pasmvars->waitflag = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//pasmvars->state = 5;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = zflag;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // waitcnt
|
||||||
|
result = GetCnt() - value1;
|
||||||
|
if (result < 0 || result >= 4)
|
||||||
|
{
|
||||||
|
//pasmvars->state = 6;
|
||||||
|
//pasmvars->pc = (pasmvars->pc - 1) & 511;
|
||||||
|
pasmvars->waitflag = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//pasmvars->state = 5;
|
||||||
|
pasmvars->waitflag = 0;
|
||||||
|
result = value1 + value2;
|
||||||
|
zflag = (result == 0);
|
||||||
|
cflag = (((value1 & value2) | ((value1 | value2) & (~result))) >> 31) & 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // waitvid
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conditionally update flags and write result
|
||||||
|
if (zcri & 8) pasmvars->zflag = zflag;
|
||||||
|
if (zcri & 4) pasmvars->cflag = cflag;
|
||||||
|
if (zcri & 2)
|
||||||
|
{
|
||||||
|
//if (dstaddr == 0x1f4) printf("outa = %8.8x\n", result);
|
||||||
|
pasmvars->mem[dstaddr] = result;
|
||||||
|
// Check if we need to update the pins
|
||||||
|
if (dstaddr == 0x1f4 || dstaddr == 0x1f6) UpdatePins();
|
||||||
|
}
|
||||||
|
//CheckSerialOut(pasmvars);
|
||||||
|
if (pasmvars->waitflag)
|
||||||
|
{
|
||||||
|
fprintf(tracefile, "XXXXXXXXXX BAD XXXXXXXXXXXXXXX\n");
|
||||||
|
pasmvars->waitflag--;
|
||||||
|
}
|
||||||
|
if (pasmvars->printflag)
|
||||||
|
PrintResults(zcri, zflag, cflag, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,89 @@
|
||||||
|
\ Define data space that will be used by the serial cog
|
||||||
|
create bufserstack 40 allot \ Data stack space
|
||||||
|
create bufserreturn 40 allot \ Return stack space
|
||||||
|
create bufserbuffer 32 allot \ Serial buffer
|
||||||
|
create bufserrdindex 0 , \ Read index
|
||||||
|
create bufserwrindex 0 , \ Write index
|
||||||
|
|
||||||
|
\ This word runs in a separate cog and writes input characters into the buffer
|
||||||
|
: bufsercog
|
||||||
|
bufserbuffer
|
||||||
|
begin
|
||||||
|
getchar over bufserwrindex @ + c!
|
||||||
|
bufserwrindex dup @ 1 + 31 and swap !
|
||||||
|
again ;
|
||||||
|
|
||||||
|
\ This word replaces the old KEY word with one that reads from the buffer
|
||||||
|
: bufkey
|
||||||
|
bufserrdindex @
|
||||||
|
begin
|
||||||
|
dup
|
||||||
|
bufserwrindex @
|
||||||
|
-
|
||||||
|
until
|
||||||
|
bufserbuffer + c@
|
||||||
|
bufserrdindex dup @ 1 + 31 and swap !
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This is the cog configuration structure used by the serial cog
|
||||||
|
create bufserconfig \ Forth cog config structure
|
||||||
|
' bufsercog >body , \ Get execution token for TOGGLE
|
||||||
|
bufserstack , \ Initial value of stack ptr
|
||||||
|
bufserstack , \ Empty value for stack ptr
|
||||||
|
bufserreturn , \ Initial value of return ptr
|
||||||
|
bufserreturn , \ Empty value for return ptr
|
||||||
|
|
||||||
|
\ This word starts a cog running the BUFSER word
|
||||||
|
: startbufsercog forth @ bufserconfig cognew ;
|
||||||
|
|
||||||
|
\ This word starts the serial cog and sets key to the new one
|
||||||
|
: bufser startbufsercog ['] bufkey is key ;
|
||||||
|
|
||||||
|
\ Buffer the serial input into memory until an ESC is received
|
||||||
|
: bufferit here 256 + dup
|
||||||
|
." Buffering serial input to memory" cr
|
||||||
|
." Enter <ESC> to exit" cr
|
||||||
|
begin
|
||||||
|
key dup 27 <>
|
||||||
|
while
|
||||||
|
over c! 1+
|
||||||
|
repeat
|
||||||
|
drop over -
|
||||||
|
\ over infile cog!
|
||||||
|
;
|
||||||
|
|
||||||
|
\ Determine the length of the current line
|
||||||
|
: linelen ( addr count -- addr len )
|
||||||
|
>r dup ( addr ptr ) ( left )
|
||||||
|
begin
|
||||||
|
r@ 0 <=
|
||||||
|
if over - r> drop exit then
|
||||||
|
dup c@ dup 10 = swap 13 = or
|
||||||
|
if over - r> drop exit then
|
||||||
|
1+ r> 1- >r
|
||||||
|
again
|
||||||
|
;
|
||||||
|
|
||||||
|
\ Variables to store the buffer address and count
|
||||||
|
variable evalbufaddr
|
||||||
|
variable evalbufcount
|
||||||
|
|
||||||
|
\ Evaluate a buffer containing multiple lines
|
||||||
|
: evalbuf ( addr count )
|
||||||
|
evalbufcount !
|
||||||
|
evalbufaddr !
|
||||||
|
begin
|
||||||
|
evalbufcount @ 0 >
|
||||||
|
while
|
||||||
|
evalbufaddr @ evalbufcount @
|
||||||
|
linelen
|
||||||
|
dup 1+ dup
|
||||||
|
evalbufaddr @ + evalbufaddr !
|
||||||
|
evalbufcount @ swap - evalbufcount !
|
||||||
|
over over type cr
|
||||||
|
evaluate
|
||||||
|
repeat
|
||||||
|
;
|
||||||
|
|
||||||
|
\ Redefine switch to use buffered serial
|
||||||
|
\ : switch bufser ;
|
|
@ -0,0 +1,94 @@
|
||||||
|
Changes in pfth 1.03
|
||||||
|
|
||||||
|
1. Added umod and u/ words
|
||||||
|
|
||||||
|
2. Fixed the #, udmod and ud/ words to handle numbers with the MSB set.
|
||||||
|
These changes fix a problem with the u. word when the MSB is set.
|
||||||
|
|
||||||
|
3. Fixed the putch PASM routine so that it only writes P30 in OUTA
|
||||||
|
|
||||||
|
|
||||||
|
Changes in pfth 1.02
|
||||||
|
|
||||||
|
1. Added ospfth.spin, which runs under Spinix
|
||||||
|
|
||||||
|
2. Added support for two simultaneous open files
|
||||||
|
|
||||||
|
3. Added bye and reboot words
|
||||||
|
|
||||||
|
4. Added sub-directory support
|
||||||
|
|
||||||
|
5. Added CD word to change the working directory
|
||||||
|
|
||||||
|
6. Modified the s" word to work in the interpretation mode
|
||||||
|
|
||||||
|
7. Added a kernel word to make constants and values more efficient
|
||||||
|
|
||||||
|
|
||||||
|
Changes in pfth 1.00
|
||||||
|
|
||||||
|
1. Fixed the FOR and NEXT words
|
||||||
|
|
||||||
|
2. Fixed a bug in UNLOOP
|
||||||
|
|
||||||
|
3. Added create-file, file-write, file-line, file-flush, file-close and
|
||||||
|
delete-file
|
||||||
|
|
||||||
|
4. Added linux.fth that implements simple ls, rm, cp and cat commands
|
||||||
|
|
||||||
|
5. Added sdutils.fth that contains some file utilities
|
||||||
|
|
||||||
|
6. Added TED -- a tiny text editor
|
||||||
|
|
||||||
|
7. Changed SAVE to EESAVE in i2c.fth
|
||||||
|
|
||||||
|
|
||||||
|
Changes in pfth 0.89
|
||||||
|
|
||||||
|
1. Changed the dictionary word structure to use 16-bit pointers instead of 32
|
||||||
|
bits.
|
||||||
|
|
||||||
|
2. Changed the execution list in compiled words to use 16-bit execution tokens
|
||||||
|
instead of 32 bits.
|
||||||
|
|
||||||
|
3. Changed the positions of the code pointer and DOES pointer to make the inner
|
||||||
|
loop more efficient. It now runs about 25% faster.
|
||||||
|
|
||||||
|
4. Changed SEE back to printing "_lit" for numbers.
|
||||||
|
|
||||||
|
5. Implemented a _loop kernel word to make DO-LOOP faster.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in pfth 0.83
|
||||||
|
|
||||||
|
1. Changed SEE in see.fth so that it doesn't print "_lit" for numbers
|
||||||
|
|
||||||
|
2. Added bufser.fth that contains a buffered serial driver
|
||||||
|
|
||||||
|
3. Added a BUFFERIT word in bufser.fth that reads the serial input into memory
|
||||||
|
until it encounters an "ESC" character.
|
||||||
|
|
||||||
|
4. Added an EVALBUF word in bufser.fth that will evaluate multiple lines in a
|
||||||
|
memory buffer
|
||||||
|
|
||||||
|
5. Updated the readme.txt file with text contributed by Loopy
|
||||||
|
|
||||||
|
6. Updated the readme.txt file with a description of the dictionary word format
|
||||||
|
|
||||||
|
7. Added a SAVE word to i2c.fth that will write the current hub RAM image to
|
||||||
|
EEPROM. Note: The small Spin program at the end of memory must have been
|
||||||
|
preserved for this to boot properly.
|
||||||
|
|
||||||
|
8. Changed the CR word so that it emits both a carriage return and a line feed.
|
||||||
|
|
||||||
|
9. Added CASE, ENDCASE, OF and ENDOF to init.fth
|
||||||
|
|
||||||
|
10. Improved WAITCNT and MS in propwords.fth. Removed INA!
|
||||||
|
|
||||||
|
11. Fixed LIST-FILES in sd.fth to skip over deleted files in the directory
|
||||||
|
|
||||||
|
12. Changed the execution token so that it points to the code pointer instead
|
||||||
|
of the beginning of the word in the dictionary
|
||||||
|
|
||||||
|
13. Made KEY a deferred word so that it can be re-assigned to the serial input
|
||||||
|
after reading the FILEs in memory
|
|
@ -0,0 +1,608 @@
|
||||||
|
\ This program was written by Lennart Benschop and converted to ANS Forth by
|
||||||
|
\ by Jeff Fox. It was further modified by Dave Hein to run under pfth. The
|
||||||
|
\ orignal source is available at http://www.ultatechnology.com/chess.html.
|
||||||
|
|
||||||
|
HEX
|
||||||
|
|
||||||
|
: scroll cr ;
|
||||||
|
: cls page ;
|
||||||
|
: key? 1 ;
|
||||||
|
: off false swap ! ;
|
||||||
|
: >defer 2 + w@ 4 - ;
|
||||||
|
|
||||||
|
3 constant maxlevel
|
||||||
|
create bp0
|
||||||
|
maxlevel 1 + c0 * allot
|
||||||
|
|
||||||
|
variable bpv
|
||||||
|
|
||||||
|
: bp bpv @ ;
|
||||||
|
: b@ bpv @ + c@ ;
|
||||||
|
: b! bpv @ + c! ;
|
||||||
|
|
||||||
|
: boardvar create ,
|
||||||
|
does> c@ bpv @ + ;
|
||||||
|
0c boardvar start
|
||||||
|
0d boardvar castlew
|
||||||
|
0e boardvar castleb
|
||||||
|
0f boardvar ep
|
||||||
|
1c boardvar starting
|
||||||
|
1d boardvar piece
|
||||||
|
1e boardvar best
|
||||||
|
1f boardvar farther?
|
||||||
|
2c boardvar wlcastle?
|
||||||
|
2d boardvar blcastle?
|
||||||
|
2e boardvar check
|
||||||
|
2f boardvar pawnmove
|
||||||
|
3c boardvar kingw
|
||||||
|
3d boardvar kingb
|
||||||
|
3e boardvar inpassing
|
||||||
|
3f boardvar advance
|
||||||
|
4c boardvar valuew
|
||||||
|
5c boardvar alfa
|
||||||
|
6c boardvar beta
|
||||||
|
7c boardvar (eval)
|
||||||
|
8c boardvar highest
|
||||||
|
9c boardvar cutoff
|
||||||
|
ac boardvar valueb
|
||||||
|
bc boardvar played
|
||||||
|
|
||||||
|
variable level
|
||||||
|
|
||||||
|
variable lastcnt
|
||||||
|
|
||||||
|
: +level
|
||||||
|
bp dup c0 + c0 cmove
|
||||||
|
c0 bpv +! 1 level +! ;
|
||||||
|
|
||||||
|
: -level
|
||||||
|
-c0 bpv +! -1 level +! ;
|
||||||
|
|
||||||
|
|
||||||
|
create symbols
|
||||||
|
|
||||||
|
CHAR . , CHAR p , CHAR k , CHAR b ,
|
||||||
|
CHAR r , CHAR q , CHAR K ,
|
||||||
|
|
||||||
|
create values
|
||||||
|
0 , 40 , c0 , c0 , 140 , 240 , 3000 ,
|
||||||
|
|
||||||
|
: .board
|
||||||
|
cls
|
||||||
|
0 0 at-xy 20 spaces
|
||||||
|
cr 2 spaces
|
||||||
|
[CHAR] H 1 + [CHAR] A do i emit 2 spaces loop
|
||||||
|
bp 20 + 8 0 do
|
||||||
|
cr 20 spaces
|
||||||
|
cr [CHAR] 8 i - emit
|
||||||
|
0a 2 do space
|
||||||
|
dup i + c@ dup
|
||||||
|
07 and cells symbols + 1 type
|
||||||
|
dup 80 and if ." W" drop else
|
||||||
|
if ." B" else ." ." then
|
||||||
|
then
|
||||||
|
loop
|
||||||
|
10 +
|
||||||
|
loop cr drop ;
|
||||||
|
|
||||||
|
: .pos
|
||||||
|
10 /mod
|
||||||
|
swap 2 - [CHAR] A + emit
|
||||||
|
[CHAR] 8 2 + swap - emit ;
|
||||||
|
|
||||||
|
\ constants that indicate the directions on the board
|
||||||
|
-11 constant nw -0f constant no
|
||||||
|
0f constant zw 11 constant zo
|
||||||
|
-10 constant n 10 constant z
|
||||||
|
-1 constant w 1 constant o
|
||||||
|
|
||||||
|
create spring
|
||||||
|
-12 , -21 , -1f , -0e , 12 , 21 , 1f , 0e ,
|
||||||
|
|
||||||
|
defer tmove
|
||||||
|
|
||||||
|
defer attacktest
|
||||||
|
|
||||||
|
: mine?
|
||||||
|
b@ dup 0= 0= swap 80 and start c@ = and ;
|
||||||
|
|
||||||
|
variable movits
|
||||||
|
|
||||||
|
: moveit
|
||||||
|
starting c@ best c! 1 farther? c!
|
||||||
|
begin
|
||||||
|
best c@ over + dup best c!
|
||||||
|
dup mine? over b@ 87 = or 0=
|
||||||
|
farther? c@ and while
|
||||||
|
tmove
|
||||||
|
b@ 0= farther? c!
|
||||||
|
repeat
|
||||||
|
drop drop
|
||||||
|
1 movits +! ;
|
||||||
|
|
||||||
|
: Bishop
|
||||||
|
no nw zo zw moveit moveit moveit moveit ;
|
||||||
|
|
||||||
|
: Rook
|
||||||
|
n o z w moveit moveit moveit moveit ;
|
||||||
|
|
||||||
|
: Queen
|
||||||
|
n o z w no nw zo zw 8 0 do moveit loop ;
|
||||||
|
|
||||||
|
: Knight
|
||||||
|
8 0 do
|
||||||
|
i cells spring + @
|
||||||
|
starting c@ + dup best c!
|
||||||
|
dup mine? swap b@ 87 = or 0=
|
||||||
|
if tmove then
|
||||||
|
loop ;
|
||||||
|
|
||||||
|
: ?castle
|
||||||
|
start c@ 80 = if castlew else castleb then c@ check c@ 0= and ;
|
||||||
|
|
||||||
|
: ?lcastle
|
||||||
|
start c@ 80 = if wlcastle? else blcastle? then c@ check c@ 0= and ;
|
||||||
|
|
||||||
|
: king
|
||||||
|
n o z w no nw zo zw 8 0 do
|
||||||
|
starting c@ + dup best c!
|
||||||
|
dup mine? swap b@ 87 = or 0=
|
||||||
|
if tmove then
|
||||||
|
loop
|
||||||
|
?castle if 28 start c@ if 70 + then
|
||||||
|
dup bp + 1- @ 0=
|
||||||
|
if
|
||||||
|
dup 1- attacktest 0=
|
||||||
|
if
|
||||||
|
best c! tmove
|
||||||
|
else drop then
|
||||||
|
else drop then
|
||||||
|
then
|
||||||
|
?lcastle if 24 start c@ if 70 + then
|
||||||
|
dup bp + @ over bp + 1- @ or 0=
|
||||||
|
if
|
||||||
|
dup 1 + attacktest 0=
|
||||||
|
if
|
||||||
|
best c! tmove
|
||||||
|
else drop then
|
||||||
|
else drop then
|
||||||
|
then ;
|
||||||
|
|
||||||
|
: Pawnrow
|
||||||
|
start c@ if negate then ;
|
||||||
|
|
||||||
|
: Pawnz
|
||||||
|
dup best c!
|
||||||
|
f0 and start c@ if 20 else 90 then =
|
||||||
|
if 6 2 do i advance c! tmove loop
|
||||||
|
else tmove then
|
||||||
|
0 pawnmove c! 0 inpassing c! 0 advance c! ;
|
||||||
|
|
||||||
|
: Pawn
|
||||||
|
starting c@ z Pawnrow +
|
||||||
|
dup b@ if
|
||||||
|
drop
|
||||||
|
else
|
||||||
|
dup Pawnz
|
||||||
|
z Pawnrow + dup b@ if
|
||||||
|
drop
|
||||||
|
else
|
||||||
|
starting c@ f0 and
|
||||||
|
start c@ if 80 else 30 then =
|
||||||
|
if starting c@ 0f and pawnmove c!
|
||||||
|
Pawnz
|
||||||
|
else drop
|
||||||
|
then
|
||||||
|
then
|
||||||
|
then
|
||||||
|
zw zo 2 0 do
|
||||||
|
Pawnrow starting c@ +
|
||||||
|
dup f0 and start c@ if 40 else 70 then =
|
||||||
|
over 0f and ep c@ = and
|
||||||
|
if 1 inpassing c!
|
||||||
|
dup Pawnz
|
||||||
|
then
|
||||||
|
dup b@ dup 0= 2 pick mine? or
|
||||||
|
swap 87 = or
|
||||||
|
if drop else Pawnz then
|
||||||
|
loop ;
|
||||||
|
|
||||||
|
create pieces
|
||||||
|
|
||||||
|
' noop , ' Pawn , ' Knight , ' Bishop , ' Rook , ' Queen , ' king ,
|
||||||
|
|
||||||
|
: piecemove
|
||||||
|
\ using above jump table for each type of piece - jump table uses , (CELLS)
|
||||||
|
piece c@ cells pieces + @ execute ;
|
||||||
|
|
||||||
|
: ?piecemove
|
||||||
|
starting c@ dup mine? if
|
||||||
|
b@ 07 and piece c!
|
||||||
|
0 pawnmove c! 0 inpassing c! 0 advance c!
|
||||||
|
piecemove
|
||||||
|
else drop then ;
|
||||||
|
|
||||||
|
: allmoves
|
||||||
|
[char] . emit
|
||||||
|
start c@ 0= if
|
||||||
|
22 starting c!
|
||||||
|
8 0 do
|
||||||
|
8 0 do
|
||||||
|
?piecemove starting c@ 1 + starting c!
|
||||||
|
loop
|
||||||
|
starting c@ 8 + starting c!
|
||||||
|
loop
|
||||||
|
else
|
||||||
|
92 starting c!
|
||||||
|
8 0 do
|
||||||
|
8 0 do
|
||||||
|
?piecemove starting c@ 1 + starting c!
|
||||||
|
loop
|
||||||
|
starting c@ 18 - starting c!
|
||||||
|
loop
|
||||||
|
then ;
|
||||||
|
|
||||||
|
variable attack
|
||||||
|
|
||||||
|
: ?attack
|
||||||
|
best c@ dup mine? 0=
|
||||||
|
swap b@ 07 and piece c@ = and
|
||||||
|
attack @ or attack ! ;
|
||||||
|
|
||||||
|
: attacked?
|
||||||
|
attack off 0 7 1 do
|
||||||
|
i piece c!
|
||||||
|
piecemove
|
||||||
|
attack @ if drop 1 leave then
|
||||||
|
loop ;
|
||||||
|
|
||||||
|
variable starting'
|
||||||
|
variable best'
|
||||||
|
variable start'
|
||||||
|
variable tmove'
|
||||||
|
|
||||||
|
: settest
|
||||||
|
starting c@ starting' c!
|
||||||
|
best c@ best' c!
|
||||||
|
start c@ start' c!
|
||||||
|
['] tmove >defer tmove' !
|
||||||
|
['] ?attack is tmove ;
|
||||||
|
|
||||||
|
: po@
|
||||||
|
starting' c@ starting c!
|
||||||
|
best' c@ best c!
|
||||||
|
start' c@ start c!
|
||||||
|
tmove' @ is tmove ;
|
||||||
|
|
||||||
|
: changecolor
|
||||||
|
start c@ 80 xor start c! ;
|
||||||
|
|
||||||
|
variable endf
|
||||||
|
variable playlevel
|
||||||
|
variable #legal
|
||||||
|
variable selected
|
||||||
|
variable compcolor
|
||||||
|
variable move#
|
||||||
|
|
||||||
|
create bp1 c0 allot
|
||||||
|
|
||||||
|
: endgame?
|
||||||
|
start c@ if valueb else valuew then @ c1 < ;
|
||||||
|
|
||||||
|
: evalboard
|
||||||
|
valueb @ valuew @ - start c@ if negate then
|
||||||
|
55 mine? 1 and + 56 mine? 1 and + 65 mine? 1 and + 66 mine? 1 and +
|
||||||
|
changecolor 55 mine? + 56 mine? + 65 mine? + 66 mine? + changecolor
|
||||||
|
|
||||||
|
endgame? if
|
||||||
|
start c@ if kingb else kingw then c@
|
||||||
|
dup f0 and dup 20 = swap 90 = or 7 and
|
||||||
|
swap 0f and dup 2 = swap 9 = or 7 and + +
|
||||||
|
then ;
|
||||||
|
|
||||||
|
: ?check
|
||||||
|
settest
|
||||||
|
start c@ if kingw else kingb then c@
|
||||||
|
starting c! attacked? check c!
|
||||||
|
po@ ;
|
||||||
|
|
||||||
|
: (attacktest)
|
||||||
|
['] tmove >defer ['] ?attack <> if
|
||||||
|
settest
|
||||||
|
starting c!
|
||||||
|
attacked?
|
||||||
|
po@
|
||||||
|
else drop true
|
||||||
|
then ;
|
||||||
|
|
||||||
|
' (attacktest) is attacktest
|
||||||
|
|
||||||
|
variable seed
|
||||||
|
|
||||||
|
: rnd
|
||||||
|
seed @ 743 * 43 + dup seed ! ;
|
||||||
|
\ 1 ;
|
||||||
|
|
||||||
|
: domove
|
||||||
|
best c@ b@ 7 and cells values + @ negate start c@
|
||||||
|
if valueb else valuew then +!
|
||||||
|
starting c@ b@ best c@ b!
|
||||||
|
0 starting c@ b!
|
||||||
|
advance c@ if
|
||||||
|
advance c@ dup cells values + @ 40 - start c@
|
||||||
|
if valueb else valueb then +!
|
||||||
|
start c@ or best c@ b!
|
||||||
|
then
|
||||||
|
piece c@ 4 = if
|
||||||
|
starting c@ 0f and 2 =
|
||||||
|
if
|
||||||
|
0 start c@ if wlcastle? else blcastle? then c!
|
||||||
|
then
|
||||||
|
starting c@ 0f and 9 =
|
||||||
|
if
|
||||||
|
0 start c@ if castlew else castleb then c!
|
||||||
|
then
|
||||||
|
then
|
||||||
|
piece c@ 6 = if
|
||||||
|
0 0 start c@ if castlew else castleb then dup >r c!
|
||||||
|
r> 1f + c!
|
||||||
|
best c@ starting c@ - 2 =
|
||||||
|
if
|
||||||
|
4 start c@ or best c@ 1- b!
|
||||||
|
0 best c@ 1 + b!
|
||||||
|
then
|
||||||
|
best c@ starting c@ - -2 =
|
||||||
|
if
|
||||||
|
4 start c@ or best c@ 1 + b!
|
||||||
|
0 best c@ 2 - b!
|
||||||
|
then
|
||||||
|
best c@ start c@ if kingw else kingb then c!
|
||||||
|
then
|
||||||
|
inpassing c@ if
|
||||||
|
0 best c@ n Pawnrow + b!
|
||||||
|
-40 start c@ if valueb else valuew then +!
|
||||||
|
then
|
||||||
|
pawnmove c@ ep c! ;
|
||||||
|
|
||||||
|
: deeper
|
||||||
|
cutoff @
|
||||||
|
invert if
|
||||||
|
+level
|
||||||
|
domove
|
||||||
|
?check check c@ if -level exit then
|
||||||
|
-1 played c0 - !
|
||||||
|
level @ playlevel @ = if
|
||||||
|
evalboard
|
||||||
|
(eval) c0 - !
|
||||||
|
else
|
||||||
|
alfa @ highest !
|
||||||
|
alfa @ negate beta @ negate alfa ! beta !
|
||||||
|
changecolor
|
||||||
|
0 played !
|
||||||
|
allmoves
|
||||||
|
played @ 0= if
|
||||||
|
?check check c@ if -2000 highest ! else 0 highest ! then
|
||||||
|
then
|
||||||
|
highest @ negate
|
||||||
|
(eval) c0 - !
|
||||||
|
then
|
||||||
|
-level
|
||||||
|
(eval) @ highest @ max
|
||||||
|
highest !
|
||||||
|
highest @ beta @ > if TRUE cutoff ! then
|
||||||
|
|
||||||
|
|
||||||
|
then ;
|
||||||
|
|
||||||
|
: analyse
|
||||||
|
+level
|
||||||
|
domove
|
||||||
|
?check check c@ 0= if
|
||||||
|
1 #legal +!
|
||||||
|
changecolor
|
||||||
|
['] tmove >defer
|
||||||
|
['] deeper is tmove
|
||||||
|
0 played !
|
||||||
|
allmoves
|
||||||
|
is tmove
|
||||||
|
played @ 0= if
|
||||||
|
?check check c@ if -2000 highest ! else 0 highest ! then
|
||||||
|
then
|
||||||
|
highest @ beta c0 - @ = if
|
||||||
|
rnd 2000 > if #legal @ selected ! then
|
||||||
|
then
|
||||||
|
highest @ beta c0 - @ < if
|
||||||
|
#legal @ selected !
|
||||||
|
highest @ beta c0 - !
|
||||||
|
then
|
||||||
|
then
|
||||||
|
-level ;
|
||||||
|
|
||||||
|
: select
|
||||||
|
+level
|
||||||
|
domove
|
||||||
|
?check check c@ 0= if
|
||||||
|
1 #legal +!
|
||||||
|
#legal @ selected @ = if
|
||||||
|
bp bp1 c0 cmove
|
||||||
|
starting c@ .pos ." -" best c@ .pos space
|
||||||
|
then
|
||||||
|
then
|
||||||
|
-level ;
|
||||||
|
|
||||||
|
: against
|
||||||
|
+level
|
||||||
|
domove
|
||||||
|
?check check c@ 0= if
|
||||||
|
1 #legal +!
|
||||||
|
then
|
||||||
|
-level ;
|
||||||
|
|
||||||
|
: compmove
|
||||||
|
.board
|
||||||
|
['] analyse is tmove
|
||||||
|
0 #legal !
|
||||||
|
-4000 alfa ! 4000 beta !
|
||||||
|
|
||||||
|
\ 0 18 at-xy cr
|
||||||
|
scroll
|
||||||
|
|
||||||
|
\ 28 spaces
|
||||||
|
start c@ if 1 move# +! move# @ 3 .r space else 4 spaces then
|
||||||
|
?check check c@ if ." Check" then
|
||||||
|
1 selected !
|
||||||
|
allmoves
|
||||||
|
#legal @ 0= if
|
||||||
|
check c@ if
|
||||||
|
." mate"
|
||||||
|
else
|
||||||
|
." Pat"
|
||||||
|
then
|
||||||
|
TRUE endf !
|
||||||
|
else
|
||||||
|
['] select is tmove
|
||||||
|
0 #legal !
|
||||||
|
allmoves
|
||||||
|
bp1 bp0 c0 cmove
|
||||||
|
changecolor
|
||||||
|
['] against is tmove
|
||||||
|
0 #legal !
|
||||||
|
allmoves
|
||||||
|
?check check c@ if ." Check" then
|
||||||
|
#legal @ 0= if
|
||||||
|
check c@ if
|
||||||
|
." mate"
|
||||||
|
else
|
||||||
|
." Pat"
|
||||||
|
then
|
||||||
|
TRUE endf !
|
||||||
|
then
|
||||||
|
then
|
||||||
|
.board ;
|
||||||
|
|
||||||
|
variable startingm
|
||||||
|
variable bestm
|
||||||
|
variable personmove
|
||||||
|
|
||||||
|
: legal
|
||||||
|
startingm @ starting c@ =
|
||||||
|
bestm @ best c@ = and
|
||||||
|
personmove @ advance c@ = and
|
||||||
|
if
|
||||||
|
+level
|
||||||
|
domove
|
||||||
|
?check check c@ 0= if
|
||||||
|
1 #legal !
|
||||||
|
bp bp1 c0 cmove
|
||||||
|
then
|
||||||
|
-level
|
||||||
|
then ;
|
||||||
|
|
||||||
|
create inputbuf 6 allot
|
||||||
|
|
||||||
|
: inpos
|
||||||
|
dup inputbuf + c@ [CHAR] A -
|
||||||
|
dup 8 u<
|
||||||
|
rot inputbuf + 1 + c@ [CHAR] 1 -
|
||||||
|
dup 8 u< rot and
|
||||||
|
swap 7 swap - 10 * rot + 22 + ;
|
||||||
|
|
||||||
|
: promote
|
||||||
|
0 6 2 do over symbols i cells + c@ = if drop i then loop ;
|
||||||
|
|
||||||
|
: person
|
||||||
|
begin
|
||||||
|
.board
|
||||||
|
|
||||||
|
scroll
|
||||||
|
|
||||||
|
\ 28 spaces
|
||||||
|
start c@ if 1 move# +! move# @ 3 .r else 3 spaces then
|
||||||
|
|
||||||
|
inputbuf 5 expect cr
|
||||||
|
|
||||||
|
\ [char] X emit inputbuf 5 type [char] X emit
|
||||||
|
|
||||||
|
inputbuf c@ [CHAR] Q = if quit then
|
||||||
|
0 inpos startingm !
|
||||||
|
2 inputbuf + c@ [CHAR] - = and
|
||||||
|
3 inpos bestm !
|
||||||
|
and
|
||||||
|
bestm @ f0 and start c@ if 20 else 90 then =
|
||||||
|
startingm b@ 07 and 1 = and
|
||||||
|
if
|
||||||
|
." What piece? " 0 0 begin drop drop key promote dup until
|
||||||
|
personmove ! emit
|
||||||
|
else
|
||||||
|
0 personmove !
|
||||||
|
then
|
||||||
|
if
|
||||||
|
['] legal is tmove
|
||||||
|
0 #legal !
|
||||||
|
startingm c@ starting c! ?piecemove
|
||||||
|
#legal @
|
||||||
|
else
|
||||||
|
0
|
||||||
|
then
|
||||||
|
dup 0= start c@ and if -1 move# +! then
|
||||||
|
until
|
||||||
|
bp1 bp0 c0 cmove
|
||||||
|
changecolor
|
||||||
|
|
||||||
|
cr
|
||||||
|
|
||||||
|
.board ;
|
||||||
|
|
||||||
|
: setmove
|
||||||
|
compcolor @ 0< start c@ 80 = = if compmove else person then ;
|
||||||
|
|
||||||
|
variable manVsMachine
|
||||||
|
|
||||||
|
: askcolor
|
||||||
|
manVSmachine @
|
||||||
|
if ." Do you want White Y/N"
|
||||||
|
key dup [CHAR] Y = swap [CHAR] y = or
|
||||||
|
if 1 else -1 then compcolor !
|
||||||
|
then ;
|
||||||
|
|
||||||
|
: asklevel
|
||||||
|
cr ." Level? 2-"
|
||||||
|
maxlevel . key [CHAR] 0 - 2 max maxlevel min playlevel !
|
||||||
|
cls ;
|
||||||
|
|
||||||
|
: init
|
||||||
|
0 level ! bp0 bpv !
|
||||||
|
bp c0 87 fill
|
||||||
|
4 2 3 6 5 3 2 4 8 0 do bp 22 + i + c! loop
|
||||||
|
bp 32 + 8 01 fill
|
||||||
|
bp 42 + 8 00 fill bp 52 + 8 00 fill
|
||||||
|
bp 62 + 8 00 fill bp 72 + 8 00 fill
|
||||||
|
bp 82 + 8 81 fill
|
||||||
|
84 82 83 86 85 83 82 84 8 0 do bp 92 + i + c! loop
|
||||||
|
1 castlew c! 1 castleb c! 0 ep c! 1 wlcastle? c! 1 blcastle? c! 0 advance c!
|
||||||
|
80 start c! 96 kingw c! 26 kingb c!
|
||||||
|
askcolor cr asklevel
|
||||||
|
0 move# ! 0 endf !
|
||||||
|
0 check c! 9c0 valuew ! 9c0 valueb ! ;
|
||||||
|
|
||||||
|
: play
|
||||||
|
begin setmove endf @ until ;
|
||||||
|
|
||||||
|
: games
|
||||||
|
begin init play again ;
|
||||||
|
|
||||||
|
: autoplay
|
||||||
|
begin setmove compcolor @ negate compcolor ! key? if quit then endf @ until ;
|
||||||
|
|
||||||
|
: auto
|
||||||
|
init -1 compcolor ! autoplay ;
|
||||||
|
|
||||||
|
: chess
|
||||||
|
cls
|
||||||
|
." ANS Forth Chess" cr
|
||||||
|
." Do you want to play against the computer? Y/N" cr
|
||||||
|
begin rnd drop key? until key
|
||||||
|
dup [CHAR] Y = swap [CHAR] y = or dup manVsMachine !
|
||||||
|
if games else auto then ;
|
||||||
|
|
||||||
|
decimal
|
|
@ -0,0 +1,145 @@
|
||||||
|
( This program checks for all 133 ANS Forth core words )
|
||||||
|
|
||||||
|
: checkword 1 + ' 0 =
|
||||||
|
if swap 1 + swap source type ." failed" 13 emit 10 emit then ;
|
||||||
|
|
||||||
|
: checkdone swap dup
|
||||||
|
if swap dup rot rot swap - . ." out of "
|
||||||
|
else drop ." All " then
|
||||||
|
. ." ANS Forth core words implemented" 13 emit 10 emit ;
|
||||||
|
|
||||||
|
0 0
|
||||||
|
checkword !
|
||||||
|
checkword #
|
||||||
|
checkword #>
|
||||||
|
checkword #S
|
||||||
|
checkword '
|
||||||
|
checkword (
|
||||||
|
checkword *
|
||||||
|
checkword */
|
||||||
|
checkword */MOD
|
||||||
|
checkword +
|
||||||
|
checkword +!
|
||||||
|
checkword +LOOP
|
||||||
|
checkword ,
|
||||||
|
checkword -
|
||||||
|
checkword .
|
||||||
|
checkword ."
|
||||||
|
checkword /
|
||||||
|
checkword /MOD
|
||||||
|
checkword 0<
|
||||||
|
checkword 0=
|
||||||
|
checkword 1+
|
||||||
|
checkword 1-
|
||||||
|
checkword 2!
|
||||||
|
checkword 2*
|
||||||
|
checkword 2/
|
||||||
|
checkword 2@
|
||||||
|
checkword 2DROP
|
||||||
|
checkword 2DUP
|
||||||
|
checkword 2OVER
|
||||||
|
checkword 2SWAP
|
||||||
|
checkword :
|
||||||
|
checkword ;
|
||||||
|
checkword <
|
||||||
|
checkword <#
|
||||||
|
checkword =
|
||||||
|
checkword >
|
||||||
|
checkword >BODY
|
||||||
|
checkword >IN
|
||||||
|
checkword >NUMBER
|
||||||
|
checkword >R
|
||||||
|
checkword ?DUP
|
||||||
|
checkword @
|
||||||
|
checkword ABORT
|
||||||
|
checkword ABORT"
|
||||||
|
checkword ABS
|
||||||
|
checkword ACCEPT
|
||||||
|
checkword ALIGN
|
||||||
|
checkword ALIGNED
|
||||||
|
checkword ALLOT
|
||||||
|
checkword AND
|
||||||
|
checkword BASE
|
||||||
|
checkword BEGIN
|
||||||
|
checkword BL
|
||||||
|
checkword C!
|
||||||
|
checkword C,
|
||||||
|
checkword C@
|
||||||
|
checkword CELL+
|
||||||
|
checkword CELLS
|
||||||
|
checkword CHAR
|
||||||
|
checkword CHAR+
|
||||||
|
checkword CHARS
|
||||||
|
checkword CONSTANT
|
||||||
|
checkword COUNT
|
||||||
|
checkword CR
|
||||||
|
checkword CREATE
|
||||||
|
checkword DECIMAL
|
||||||
|
checkword DEPTH
|
||||||
|
checkword DO
|
||||||
|
checkword DOES>
|
||||||
|
checkword DROP
|
||||||
|
checkword DUP
|
||||||
|
checkword ELSE
|
||||||
|
checkword EMIT
|
||||||
|
checkword ENVIRONMENT?
|
||||||
|
checkword EVALUATE
|
||||||
|
checkword EXECUTE
|
||||||
|
checkword EXIT
|
||||||
|
checkword FILL
|
||||||
|
checkword FIND
|
||||||
|
checkword FM/MOD
|
||||||
|
checkword HERE
|
||||||
|
checkword HOLD
|
||||||
|
checkword I
|
||||||
|
checkword IF
|
||||||
|
checkword IMMEDIATE
|
||||||
|
checkword INVERT
|
||||||
|
checkword J
|
||||||
|
checkword KEY
|
||||||
|
checkword LEAVE
|
||||||
|
checkword LITERAL
|
||||||
|
checkword LOOP
|
||||||
|
checkword LSHIFT
|
||||||
|
checkword M*
|
||||||
|
checkword MAX
|
||||||
|
checkword MIN
|
||||||
|
checkword MOD
|
||||||
|
checkword MOVE
|
||||||
|
checkword NEGATE
|
||||||
|
checkword OR
|
||||||
|
checkword OVER
|
||||||
|
checkword POSTPONE
|
||||||
|
checkword QUIT
|
||||||
|
checkword R>
|
||||||
|
checkword R@
|
||||||
|
checkword RECURSE
|
||||||
|
checkword REPEAT
|
||||||
|
checkword ROT
|
||||||
|
checkword RSHIFT
|
||||||
|
checkword S"
|
||||||
|
checkword S>D
|
||||||
|
checkword SIGN
|
||||||
|
checkword SM/REM
|
||||||
|
checkword SOURCE
|
||||||
|
checkword SPACE
|
||||||
|
checkword SPACES
|
||||||
|
checkword STATE
|
||||||
|
checkword SWAP
|
||||||
|
checkword THEN
|
||||||
|
checkword TYPE
|
||||||
|
checkword U.
|
||||||
|
checkword U<
|
||||||
|
checkword UM*
|
||||||
|
checkword UM/MOD
|
||||||
|
checkword UNLOOP
|
||||||
|
checkword UNTIL
|
||||||
|
checkword VARIABLE
|
||||||
|
checkword WHILE
|
||||||
|
checkword WORD
|
||||||
|
checkword XOR
|
||||||
|
checkword [
|
||||||
|
checkword [']
|
||||||
|
checkword [CHAR]
|
||||||
|
checkword ]
|
||||||
|
checkdone
|
|
@ -0,0 +1,57 @@
|
||||||
|
( This program checks for all 45 ANS Forth core ext words )
|
||||||
|
|
||||||
|
: checkword 1 + ' 0 =
|
||||||
|
if swap 1 + swap source type ." failed" 13 emit 10 emit then ;
|
||||||
|
|
||||||
|
: checkdone swap dup
|
||||||
|
if swap dup rot rot swap - . ." out of "
|
||||||
|
else drop ." All " then
|
||||||
|
. ." ANS Forth core ext words implemented" 13 emit 10 emit ;
|
||||||
|
|
||||||
|
0 0
|
||||||
|
checkword #tib
|
||||||
|
checkword .(
|
||||||
|
checkword .r
|
||||||
|
checkword 0<>
|
||||||
|
checkword 0>
|
||||||
|
checkword 2>r
|
||||||
|
checkword 2r>
|
||||||
|
checkword 2r@
|
||||||
|
checkword :noname
|
||||||
|
checkword <>
|
||||||
|
checkword ?do
|
||||||
|
checkword again
|
||||||
|
checkword c"
|
||||||
|
checkword case
|
||||||
|
checkword compile,
|
||||||
|
checkword convert
|
||||||
|
checkword endcase
|
||||||
|
checkword endof
|
||||||
|
checkword erase
|
||||||
|
checkword expect
|
||||||
|
checkword false
|
||||||
|
checkword hex
|
||||||
|
checkword marker
|
||||||
|
checkword nip
|
||||||
|
checkword of
|
||||||
|
checkword pad
|
||||||
|
checkword parse
|
||||||
|
checkword pick
|
||||||
|
checkword query
|
||||||
|
checkword refill
|
||||||
|
checkword restore-input
|
||||||
|
checkword roll
|
||||||
|
checkword save-input
|
||||||
|
checkword source-id
|
||||||
|
checkword span
|
||||||
|
checkword tib
|
||||||
|
checkword to
|
||||||
|
checkword true
|
||||||
|
checkword tuck
|
||||||
|
checkword u.r
|
||||||
|
checkword u>
|
||||||
|
checkword value
|
||||||
|
checkword within
|
||||||
|
checkword [compile]
|
||||||
|
checkword \
|
||||||
|
checkdone
|
|
@ -0,0 +1,29 @@
|
||||||
|
( Useful non-standard words )
|
||||||
|
: @+ dup cell+ swap @ ;
|
||||||
|
: !+ over ! cell+ ;
|
||||||
|
: c@+ dup char+ swap c@ ;
|
||||||
|
: c!+ over c! char+ ;
|
||||||
|
: between 1+ within ;
|
||||||
|
: bounds over + swap ;
|
||||||
|
: buffer: create allot ;
|
||||||
|
: cell 4 ;
|
||||||
|
: cell- cell - ;
|
||||||
|
: not 0= ;
|
||||||
|
: parse-word bl word count ;
|
||||||
|
: perform @ execute ;
|
||||||
|
: >= < 0= ;
|
||||||
|
: <= > 0= ;
|
||||||
|
: -rot rot rot ;
|
||||||
|
: 2- 2 - ;
|
||||||
|
: 2+ 2 + ;
|
||||||
|
: 3dup dup 2over rot ;
|
||||||
|
: 4dup 2over 2over ;
|
||||||
|
: noop ;
|
||||||
|
: off false swap ! ;
|
||||||
|
: on true swap ! ;
|
||||||
|
: for ['] >r compile, ['] _lit compile, 0 compile, ['] >r compile, here ;
|
||||||
|
immediate
|
||||||
|
: next ['] _lit compile, 1 compile, ['] _loop compile, ['] _jz compile,
|
||||||
|
compile, ['] r> compile, ['] r> compile, ['] 2drop compile, ; immediate
|
||||||
|
: zstrlen dup begin dup c@ while 1+ repeat swap - ;
|
||||||
|
: zcount dup zstrlen ;
|
|
@ -0,0 +1,88 @@
|
||||||
|
\ ############################################################################
|
||||||
|
\ # fds.fth - This program implements a full duplex serial port. It is base
|
||||||
|
\ # on the FullDuplexSerial Spin object.
|
||||||
|
\ #
|
||||||
|
\ # Copyright (c) 2012 Dave Hein
|
||||||
|
\ # MIT Licensed
|
||||||
|
\ ############################################################################
|
||||||
|
|
||||||
|
0 value fds_cog
|
||||||
|
create fds_vars 68 allot
|
||||||
|
|
||||||
|
: fds_var create , does> @ fds_vars + ;
|
||||||
|
|
||||||
|
0 fds_var rx_head
|
||||||
|
4 fds_var rx_tail
|
||||||
|
8 fds_var tx_head
|
||||||
|
12 fds_var tx_tail
|
||||||
|
16 fds_var rx_pin
|
||||||
|
20 fds_var tx_pin
|
||||||
|
24 fds_var rxtx_mode
|
||||||
|
28 fds_var bit_ticks
|
||||||
|
32 fds_var buffer_ptr
|
||||||
|
36 fds_var rx_buffer
|
||||||
|
52 fds_var tx_buffer
|
||||||
|
|
||||||
|
hex
|
||||||
|
|
||||||
|
create fds_entry
|
||||||
|
a0bca9f0 , 80fca810 , 08bcaa54 , a0fcb201 , 2cbcb255 , 80fca804 , 08bcaa54 ,
|
||||||
|
a0fcbe01 , 2cbcbe55 , 80fca804 , 08bcae54 , 80fca804 , 08bcb054 , 80fca804 ,
|
||||||
|
08bcb454 , a0bcc05a , 80fcc010 , 627cae04 , 617cae02 , 689be85f , 68abec5f ,
|
||||||
|
a0fcc833 , 5cbcbc64 , 627cae01 , 613cb3f2 , 5c640016 , a0fcb809 , a0bcba58 ,
|
||||||
|
28fcba01 , 80bcbbf1 , 80bcba58 , 5cbcbc64 , a0bca85d , 84bca9f1 , c17ca800 ,
|
||||||
|
5c4c001f , 613cb3f2 , 30fcb601 , e4fcb81e , 28fcb617 , 60fcb6ff , 627cae01 ,
|
||||||
|
6cd4b6ff , 08bcabf0 , 80bcaa5a , 003cb655 , 84bcaa5a , 80fcaa01 , 60fcaa0f ,
|
||||||
|
083cabf0 , 5c7c0016 , 5cbcc85e , a0bca9f0 , 80fca808 , 08bcaa54 , 80fca804 ,
|
||||||
|
08bcac54 , 863caa56 , 5c680033 , 80bcac60 , 00bcc256 , 84bcac60 , 80fcac01 ,
|
||||||
|
60fcac0f , 083cac54 , 68fcc300 , 2cfcc202 , 68fcc201 , a0fcc40b , a0bcc7f1 ,
|
||||||
|
627cae04 , 617cae02 , 6ce0c201 , 29fcc201 , 70abe85f , 7497ec5f , 80bcc658 ,
|
||||||
|
5cbcc85e , a0bca863 , 84bca9f1 , c17ca800 , 5c4c004d , e4fcc446 , 5c7c0033 ,
|
||||||
|
|
||||||
|
decimal
|
||||||
|
|
||||||
|
: fds_start ( rxpin txpin mode baudrate ... )
|
||||||
|
>r
|
||||||
|
fds_vars 16 0 fill
|
||||||
|
rxtx_mode ! tx_pin ! rx_pin !
|
||||||
|
clkfreq@ r> / bit_ticks !
|
||||||
|
rx_buffer buffer_ptr !
|
||||||
|
0 dira!
|
||||||
|
fds_entry rx_head cognew
|
||||||
|
1+ dup to fds_cog
|
||||||
|
;
|
||||||
|
|
||||||
|
: fds_stop fds_cog if fds_cog 1- cogstop 0 to fds_cog then ;
|
||||||
|
|
||||||
|
: fds_rxcheck rx_tail @ rx_head @ 2dup . . cr =
|
||||||
|
if
|
||||||
|
-1
|
||||||
|
else
|
||||||
|
rx_tail @ rx_buffer + c@
|
||||||
|
rx_tail @ 1+ 15 and rx_tail !
|
||||||
|
then
|
||||||
|
;
|
||||||
|
|
||||||
|
: fds_rx begin fds_rxcheck dup -1 = while drop repeat ;
|
||||||
|
|
||||||
|
: fds_tx begin tx_tail @ tx_head @ 1+ 15 and <> until
|
||||||
|
tx_head @ tx_buffer + c!
|
||||||
|
tx_head @ 1+ 15 and tx_head !
|
||||||
|
rxtx_mode @ 8 and if fds_rx then
|
||||||
|
;
|
||||||
|
|
||||||
|
: fdstest
|
||||||
|
." Type 'q' to quit" cr
|
||||||
|
31 30 0 115200 fds_start
|
||||||
|
drop
|
||||||
|
begin
|
||||||
|
fds_rx
|
||||||
|
dup [char] q <>
|
||||||
|
while
|
||||||
|
[char] < fds_tx fds_tx [char] > fds_tx
|
||||||
|
repeat
|
||||||
|
drop
|
||||||
|
fds_stop
|
||||||
|
1 30 lshift dira!
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,217 @@
|
||||||
|
\ ############################################################################
|
||||||
|
\ # i2c.fth - This program reads and writes EEPROMs using the I2C protocol.
|
||||||
|
\ # This program is based on Mike Green's basic_i2c_driver, which is found in
|
||||||
|
\ # the Parallax Object Exchange (OBEX).
|
||||||
|
\ #
|
||||||
|
\ # The first parameter for all routines is the pin number of the clock. It
|
||||||
|
\ # is assumed that the data pin number is one greater than the clock pin
|
||||||
|
\ # number.
|
||||||
|
\ #
|
||||||
|
\ # Copyright (c) 2012 Dave Hein
|
||||||
|
\ # MIT Licensed
|
||||||
|
\ ############################################################################
|
||||||
|
|
||||||
|
: i2c_dira_sda_high dup dira@ or dira! ;
|
||||||
|
: i2c_outa_sda_high dup outa@ or outa! ;
|
||||||
|
: i2c_dira_scl_high over dira@ or dira! ;
|
||||||
|
: i2c_outa_scl_high over outa@ or outa! ;
|
||||||
|
: i2c_dira_sda_low dup invert dira@ and dira! ;
|
||||||
|
: i2c_outa_sda_low dup invert outa@ and outa! ;
|
||||||
|
: i2c_dira_scl_low over invert dira@ and dira! ;
|
||||||
|
: i2c_outa_scl_low over invert outa@ and outa! ;
|
||||||
|
|
||||||
|
\ This routine should be called before calling any of the other ones to ensure
|
||||||
|
\ that the EEPROM is in a known ready state.
|
||||||
|
: i2c_init ( scl ... )
|
||||||
|
1 swap lshift dup 2* \ sda := scl + 1
|
||||||
|
i2c_outa_scl_high \ outa[scl] := 1
|
||||||
|
i2c_dira_scl_high \ dira[scl] := 1
|
||||||
|
i2c_dira_sda_low \ dira[sda] := 0
|
||||||
|
9 0 do \ repeat 9
|
||||||
|
i2c_outa_scl_low \ outa[scl] := 0
|
||||||
|
i2c_outa_scl_high \ outa[scl[ := 1
|
||||||
|
dup ina@ and if leave then \ if ina[sda] quit
|
||||||
|
loop
|
||||||
|
2drop
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This routine sends a start bit
|
||||||
|
: i2c_start ( scl ... )
|
||||||
|
1 swap lshift dup 2* \ sda := scl + 1
|
||||||
|
i2c_outa_scl_high \ outa[scl]~~
|
||||||
|
i2c_dira_scl_high \ dira[scl]~~
|
||||||
|
i2c_outa_sda_high \ outa[sda]~~
|
||||||
|
i2c_dira_sda_high \ dira[sda]~~
|
||||||
|
i2c_outa_sda_low \ outa[sda]~
|
||||||
|
i2c_outa_scl_low \ outa[scl]~
|
||||||
|
2drop
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This routine sends a stop bit
|
||||||
|
: i2c_stop ( scl ... )
|
||||||
|
1 swap lshift dup 2* \ sda := scl + 1
|
||||||
|
i2c_outa_scl_high \ outa[scl]~~
|
||||||
|
i2c_outa_sda_high \ outa[sda]~~
|
||||||
|
i2c_dira_scl_low \ dira[scl]~
|
||||||
|
i2c_dira_sda_low \ dira[sda]~
|
||||||
|
2drop
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This routine sends one byte and returns the ACK bit
|
||||||
|
: i2c_write ( scl data ... ackbit )
|
||||||
|
23 lshift swap \ data <<= 23
|
||||||
|
1 swap lshift dup 2* \ sda := scl + 1
|
||||||
|
8 0 do \ repeat 8
|
||||||
|
rot 2* dup 0<
|
||||||
|
if
|
||||||
|
rot rot
|
||||||
|
i2c_outa_sda_high \ outa[sda] := 1
|
||||||
|
else
|
||||||
|
rot rot
|
||||||
|
i2c_outa_sda_low \ outa[sda] := 0
|
||||||
|
then
|
||||||
|
i2c_outa_scl_high \ outa[scl]~~
|
||||||
|
i2c_outa_scl_low \ dira[scl]~
|
||||||
|
loop
|
||||||
|
i2c_dira_sda_low \ dira[sda]~
|
||||||
|
i2c_outa_scl_high \ outa[scl]~~
|
||||||
|
dup ina@ and >r \ ackbit := ina[sda]
|
||||||
|
i2c_outa_scl_low \ outa[scl]~
|
||||||
|
i2c_outa_sda_low \ outa[sda]~
|
||||||
|
i2c_dira_sda_high \ dira[sda]~~
|
||||||
|
2drop drop
|
||||||
|
r> \ return ackbit
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This routine reads one byte from the EEPROM
|
||||||
|
: i2c_read ( scl ackbit ... data )
|
||||||
|
>r \ save ackbit
|
||||||
|
0 swap \ data := 0
|
||||||
|
1 swap lshift dup 2* \ sda := scl + 1
|
||||||
|
i2c_dira_sda_low \ dira[sda]~
|
||||||
|
8 0 do \ repeat 8
|
||||||
|
i2c_outa_scl_high \ outa[scl]~~
|
||||||
|
rot 2* \ data <<= 1
|
||||||
|
over ina@ and if 1 or then \ if ina[sda] data |= 1
|
||||||
|
rot rot
|
||||||
|
i2c_outa_scl_low \ outa[scl]~
|
||||||
|
loop
|
||||||
|
r> if
|
||||||
|
i2c_outa_sda_high \ outa[sda]~~
|
||||||
|
else
|
||||||
|
i2c_outa_sda_low \ outa[sda]~
|
||||||
|
then
|
||||||
|
i2c_dira_sda_high \ dira[sda]~~
|
||||||
|
i2c_outa_scl_high \ outa[scl]~~
|
||||||
|
i2c_outa_scl_low \ outa[scl]~
|
||||||
|
i2c_outa_sda_low \ outa[sda]~
|
||||||
|
2drop \ return data
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This routine reads up to one page of data from the EEPROM
|
||||||
|
: i2c_readpage ( scl devsel addrreg dataptr count ... ackbit )
|
||||||
|
>r >r \ Move count and dataptr to the return stack
|
||||||
|
dup 15 rshift 14 and rot or \ Assemble the devsel byte
|
||||||
|
dup >r rot dup dup >r \ Copy devsel and scl to the return stack
|
||||||
|
i2c_start \ Send a start bit
|
||||||
|
swap \ Arrange the scl and devsel on the stack
|
||||||
|
i2c_write drop \ Send the devsel byte
|
||||||
|
dup 8 rshift 255 and r@ swap \ Extract the second address byte
|
||||||
|
i2c_write drop \ Send the second address byte
|
||||||
|
255 and r@ swap \ Extract the third address byte
|
||||||
|
i2c_write drop \ Send it
|
||||||
|
r@ \ Get the scl from the return stack
|
||||||
|
i2c_start \ Send a start bit
|
||||||
|
r> r> 1 or over >r \ Get the scl and devsel byte and set the LSB
|
||||||
|
i2c_write drop \ Send the devsel byte
|
||||||
|
r> r> r> 1 ?do \ Get scl, dataptr and count and start do loop
|
||||||
|
over 0 i2c_read over c! 1+ \ Read a byte from the EEPROM and save it
|
||||||
|
loop
|
||||||
|
over 1 i2c_read swap c! \ Read the last byte from the EEPROM
|
||||||
|
i2c_stop \ Send a stop bit
|
||||||
|
0 \ Return the ack bit
|
||||||
|
;
|
||||||
|
|
||||||
|
variable i2c_var
|
||||||
|
|
||||||
|
\ This routine reads a byte from the specified address
|
||||||
|
: i2c_readbyte ( scl devsel addrreg )
|
||||||
|
i2c_var 1 i2c_readpage drop i2c_var c@ ;
|
||||||
|
|
||||||
|
\ This routine reads a word from the specified address
|
||||||
|
: i2c_readword ( scl devsel addrreg )
|
||||||
|
0 i2c_var ! i2c_var 2 i2c_readpage drop i2c_var @ ;
|
||||||
|
|
||||||
|
\ This routine reads a long from the specified address
|
||||||
|
: i2c_readlong ( scl devsel addrreg )
|
||||||
|
i2c_var 4 i2c_readpage drop i2c_var @ ;
|
||||||
|
|
||||||
|
\ This routine writes up to one page of data to the EEPROM
|
||||||
|
: i2c_writepage ( scl devsel addrreg dataptr count ... ackbit )
|
||||||
|
>r >r \ ( scl devsel addrreg ) r( count dataptr )
|
||||||
|
dup 15 rshift 14 and rot or \ ( scl addrreg devsel )
|
||||||
|
rot dup >r \ ( addrreg devsel scl ) r( count dataptr scl )
|
||||||
|
i2c_start \ ( addrreg devsel ) r( count dataptr scl )
|
||||||
|
r@ swap \ ( addrreg slc devsel ) r( count dataptr scl )
|
||||||
|
i2c_write drop \ ( addrreg ) r( count dataptr scl )
|
||||||
|
dup 8 rshift 255 and r@ swap
|
||||||
|
i2c_write drop
|
||||||
|
255 and r@ swap
|
||||||
|
i2c_write drop
|
||||||
|
r> r> r> 0 ?do
|
||||||
|
2dup c@ i2c_write drop 1+
|
||||||
|
loop
|
||||||
|
drop
|
||||||
|
i2c_stop
|
||||||
|
0
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This routine writes a byte to the specified address
|
||||||
|
: i2c_writebyte ( scl devsel addrreg data )
|
||||||
|
i2c_var ! i2c_var 1 i2c_writepage drop ;
|
||||||
|
|
||||||
|
\ This routine writes a word to the specified address
|
||||||
|
: i2c_writeword ( scl devsel addrreg data )
|
||||||
|
i2c_var ! i2c_var 2 i2c_writepage drop ;
|
||||||
|
|
||||||
|
\ This routine writes a long to the specified address
|
||||||
|
: i2c_writelong ( scl devsel addrreg data )
|
||||||
|
i2c_var ! i2c_var 4 i2c_writepage drop ;
|
||||||
|
|
||||||
|
\ This routine returns a zero if the EEPROM is ready after a write
|
||||||
|
\ Otherwise it returns a non-zero value
|
||||||
|
: i2c_writewait ( scl devsel addrreg )
|
||||||
|
15 rshift 14 and or
|
||||||
|
over i2c_start
|
||||||
|
over >r i2c_write
|
||||||
|
r> i2c_stop
|
||||||
|
;
|
||||||
|
|
||||||
|
\ This word will be run at startup
|
||||||
|
: startup
|
||||||
|
1 30 lshift dup outa! dira!
|
||||||
|
pfthversion type cr
|
||||||
|
;
|
||||||
|
|
||||||
|
\ Set up the cog config struct
|
||||||
|
: setupconfig
|
||||||
|
496 cog@ \ Get config struct address from PAR
|
||||||
|
dup 16 + @ \ Get the address of the return stack
|
||||||
|
4 + over 12 + ! \ Add four and set initial address of return stack
|
||||||
|
['] interpret >body \ Get the address of the Forth interpreter
|
||||||
|
over 16 + @ ! \ Write it to the return stack
|
||||||
|
['] startup >body \ Get the address of the startup word
|
||||||
|
swap ! \ Write it to the intial value of the program counter
|
||||||
|
;
|
||||||
|
|
||||||
|
\ Save the hub RAM to EEPROM
|
||||||
|
: eesave
|
||||||
|
setupconfig
|
||||||
|
28 i2c_init
|
||||||
|
512 0
|
||||||
|
do
|
||||||
|
28 160 i 64 * dup 64 i2c_writepage drop
|
||||||
|
begin 28 160 0 i2c_writewait 0= until
|
||||||
|
i 7 and 7 = if [char] . emit then
|
||||||
|
loop
|
||||||
|
;
|
|
@ -0,0 +1,400 @@
|
||||||
|
: link>flags 2 + ;
|
||||||
|
: immediate 81 last @ link>flags c! ;
|
||||||
|
: \ 100 word drop ; immediate
|
||||||
|
|
||||||
|
\ The above lines implement the words to allow for "\" comments
|
||||||
|
\ All numbers are in hex at this point.
|
||||||
|
|
||||||
|
\ DEFINE CELL SIZE
|
||||||
|
: cellsize 4 ;
|
||||||
|
: cellmask 3 ;
|
||||||
|
: compsize 2 ;
|
||||||
|
: compmask 1 ;
|
||||||
|
|
||||||
|
\ BASIC STACK WORDS
|
||||||
|
: rot 2 roll ;
|
||||||
|
: over 1 pick ;
|
||||||
|
: 2dup over over ;
|
||||||
|
: 2drop drop drop ;
|
||||||
|
: 2swap 3 roll 3 roll ;
|
||||||
|
: 2over 3 pick 3 pick ;
|
||||||
|
|
||||||
|
\ WORD HEADER ACCESSORS
|
||||||
|
: >does 2 + ;
|
||||||
|
: >body 4 + ;
|
||||||
|
: name>xt dup c@ + 4 + 0 4 - and ;
|
||||||
|
: link>name 3 + ;
|
||||||
|
: link>xt link>name name>xt ;
|
||||||
|
: link>does link>xt 2 + ;
|
||||||
|
: link>body link>xt 4 + ;
|
||||||
|
|
||||||
|
\ DEFINE BASIC WORD BUILDERS
|
||||||
|
: source tib #tib @ ;
|
||||||
|
\ : compile, , ;
|
||||||
|
: ' 20 word find 0 = 0 = and ;
|
||||||
|
: _does r> dup >r 2 + last @ link>does w! ;
|
||||||
|
: _setjmp 0a last @ link>flags c! ;
|
||||||
|
: literal 0 compile, compile, ; immediate
|
||||||
|
last @ link>body dup @ swap 2 + w! \ Patch in address of _lit
|
||||||
|
: postpone ' compile, ; immediate
|
||||||
|
: ['] ' postpone literal ; immediate
|
||||||
|
: [compile] ' postpone literal ['] compile, compile, ; immediate
|
||||||
|
: does> [compile] _does [compile] exit ; immediate
|
||||||
|
|
||||||
|
\ CONDITIONAL EXECUTION AND LOOPING
|
||||||
|
: if ['] _jz compile, here 2 allot ; immediate
|
||||||
|
: else ['] _jmp compile, here 2 + swap w! here 2 allot ; immediate
|
||||||
|
: then here swap w! ; immediate
|
||||||
|
: begin here ; immediate
|
||||||
|
: until ['] _jz compile, compile, ; immediate
|
||||||
|
: again ['] _jmp compile, compile, ; immediate
|
||||||
|
: while ['] _jz compile, here 2 allot ; immediate
|
||||||
|
: repeat ['] _jmp compile, here 2 + swap w! compile, ; immediate
|
||||||
|
: do ['] _lit compile, here 2 allot ['] drop compile,
|
||||||
|
['] swap compile, ['] >r compile, ['] >r compile, here ; immediate
|
||||||
|
: ?do ['] 2dup compile, ['] > compile, ['] _jz compile, here 2 allot
|
||||||
|
['] swap compile, ['] >r compile, ['] >r compile, here ; immediate
|
||||||
|
\ : _loop r> swap r> + r> dup >r swap dup >r > 0 = swap >r ;
|
||||||
|
: loop ['] _lit compile, 1 compile, ['] _loop compile, ['] _jz compile, compile, ['] r> compile,
|
||||||
|
['] r> compile, here swap w! ['] 2drop compile, ; immediate
|
||||||
|
: +loop ['] _loop compile, ['] _jz compile, compile, ['] r> compile,
|
||||||
|
['] r> compile, here swap w! ['] 2drop compile, ; immediate
|
||||||
|
: leave r> r> drop r> dup >r >r >r ;
|
||||||
|
: i r> r> dup >r swap >r ;
|
||||||
|
: j r> r> r> r> dup >r swap >r swap >r swap >r ;
|
||||||
|
|
||||||
|
\ DEFINE >FLAGS AND >LINK
|
||||||
|
: >flags begin 1 - dup c@ 80 and until ;
|
||||||
|
: >link >flags 2 - ;
|
||||||
|
|
||||||
|
\ DEFINE DEFER AND IS
|
||||||
|
\ Change code pointer from varfunc to deferfunc
|
||||||
|
: defer create last @ link>xt dup w@ 3 + swap w! ;
|
||||||
|
: is state @
|
||||||
|
if [compile] >body ' >does postpone literal [compile] w!
|
||||||
|
else >body ' >does w!
|
||||||
|
then ; immediate
|
||||||
|
|
||||||
|
\ REDEFINE REFILL AS A DEFERRED WORD
|
||||||
|
' refill
|
||||||
|
defer refill
|
||||||
|
is refill
|
||||||
|
|
||||||
|
\ DEFINE "(" COMMENT WORD NOW THAT WE CAN LOOP
|
||||||
|
: ( begin
|
||||||
|
#tib @ >in @
|
||||||
|
?do tib i + c@ 29 = if i 1 + >in ! r> r> drop drop exit then loop
|
||||||
|
refill 0 =
|
||||||
|
until ; immediate
|
||||||
|
|
||||||
|
( PAD AND PRINT SUPPORT )
|
||||||
|
create pad 100 allot
|
||||||
|
create printptr 4 allot
|
||||||
|
: _d2a dup 0a < if 30 else 57 then + ;
|
||||||
|
: _a2d dup 30 <
|
||||||
|
if
|
||||||
|
drop 0 1 -
|
||||||
|
else
|
||||||
|
dup 39 >
|
||||||
|
if
|
||||||
|
dup 41 <
|
||||||
|
if
|
||||||
|
drop 0 1 -
|
||||||
|
else
|
||||||
|
dup 5a >
|
||||||
|
if
|
||||||
|
dup 61 <
|
||||||
|
if
|
||||||
|
drop 0 1 -
|
||||||
|
else
|
||||||
|
dup 7a >
|
||||||
|
if
|
||||||
|
drop 0 1 -
|
||||||
|
else
|
||||||
|
57 -
|
||||||
|
then
|
||||||
|
then
|
||||||
|
else
|
||||||
|
37 -
|
||||||
|
then
|
||||||
|
then
|
||||||
|
else
|
||||||
|
30 -
|
||||||
|
then
|
||||||
|
then
|
||||||
|
dup base @ < 0 =
|
||||||
|
if
|
||||||
|
drop 0 1 -
|
||||||
|
then
|
||||||
|
;
|
||||||
|
: c!-- dup >r c! r> 1 - ;
|
||||||
|
: cprint printptr @ c! printptr @ 1 - printptr ! ;
|
||||||
|
|
||||||
|
( DOUBLE WORDS )
|
||||||
|
: s>d 0 pick 0 < ;
|
||||||
|
: m* * s>d ;
|
||||||
|
: um* * 0 ;
|
||||||
|
: d+ drop 1 roll drop + s>d ;
|
||||||
|
: d- drop 1 roll drop - s>d ;
|
||||||
|
: d* drop 1 roll drop * s>d ;
|
||||||
|
: d/ drop 1 roll drop / s>d ;
|
||||||
|
: dmod drop 1 roll drop mod s>d ;
|
||||||
|
: _u/ over over swap 1 rshift swap / dup + dup >r over * rot swap - swap < 1 + r> + ;
|
||||||
|
: u/ over 0 < if _u/ else / then ;
|
||||||
|
: ud/ drop 1 roll drop u/ 0 ;
|
||||||
|
: _umod swap dup 1 rshift 2 pick mod dup + swap 1 and + swap mod ;
|
||||||
|
: umod over 0 < if _umod else mod then ;
|
||||||
|
: udmod drop 1 roll drop umod 0 ;
|
||||||
|
|
||||||
|
( CORE WORDS )
|
||||||
|
: +! dup @ rot + swap ! ;
|
||||||
|
: /mod over over >r >r mod r> r> / ;
|
||||||
|
: [ state 0 ! ;
|
||||||
|
: ] state 1 ! ;
|
||||||
|
: r@ r> r> dup >r swap >r ;
|
||||||
|
: sm/rem >r 2dup r@ s>d d/ drop r> swap >r s>d dmod drop r> ;
|
||||||
|
: um/mod >r 2dup r@ s>d ud/ drop r> swap >r s>d udmod drop r> ;
|
||||||
|
: fm/mod over over xor 1 31 lshift and if sm/rem else sm/rem then ; ( TODO )
|
||||||
|
: */mod >r m* r> sm/rem ;
|
||||||
|
: */ */mod swap drop ;
|
||||||
|
: <# pad ff + printptr ! ;
|
||||||
|
: hold cprint ;
|
||||||
|
: # drop dup base @ umod _d2a cprint base @ u/ 0 ;
|
||||||
|
: #s begin # over over or 0 = until ;
|
||||||
|
: #> drop drop printptr @ 1 + dup pad 100 + swap - ;
|
||||||
|
: sign 0 < if 2d hold then ;
|
||||||
|
: abs dup 0 < if 0 swap - then ;
|
||||||
|
: type 0 ?do dup c@ emit 1 + loop drop ;
|
||||||
|
: ._ dup abs 0 <# #s rot sign #> type ;
|
||||||
|
: . ._ 20 emit ;
|
||||||
|
|
||||||
|
: >number dup 0 ?do >r dup c@ _a2d dup 0 < if drop r> leave else swap >r >r
|
||||||
|
base @ 0 d* r> 0 d+ r> 1 + r> 1 - then loop ;
|
||||||
|
: 0= 0 = ;
|
||||||
|
: 0< 0 < ;
|
||||||
|
: 1+ 1 + ;
|
||||||
|
: 1- 1 - ;
|
||||||
|
: 2! swap over ! cellsize + ! ;
|
||||||
|
: 2* dup + ;
|
||||||
|
: 2/ dup 80000000 and swap 1 rshift or ;
|
||||||
|
: 2@ dup cellsize + @ swap @ ;
|
||||||
|
: ?dup dup if dup then ;
|
||||||
|
: aligned cellmask + 0 cellsize - and ;
|
||||||
|
: align here aligned here - allot ;
|
||||||
|
: bl 20 ;
|
||||||
|
: c, here c! 1 allot ;
|
||||||
|
: cell+ cellsize + ;
|
||||||
|
: cells cellsize * ;
|
||||||
|
: char+ 1 + ;
|
||||||
|
: chars ;
|
||||||
|
\ : count dup char+ swap c@ ;
|
||||||
|
: char 20 word count 0= if drop 0 else c@ then ;
|
||||||
|
: [char] char postpone literal ; immediate
|
||||||
|
\ : constant create here ! cellsize allot does> @ ;
|
||||||
|
: constant create , last @ link>xt dup w@ 3 - swap w! ;
|
||||||
|
: cr 0a emit 0d emit ;
|
||||||
|
: decimal 0a base ! ;
|
||||||
|
: environment? drop drop 0 ;
|
||||||
|
: fill swap >r swap r> 0 ?do 2dup c! 1 + loop 2drop ;
|
||||||
|
: hex 10 base ! ;
|
||||||
|
: invert 0 1 - xor ;
|
||||||
|
: max 2dup < if swap then drop ;
|
||||||
|
: min 2dup > if swap then drop ;
|
||||||
|
\ : cmove >r swap r> 0 ?do 2dup c@ swap c! 1+ swap 1+ swap loop 2drop ;
|
||||||
|
: cmove> >r swap r> dup >r 1- dup >r + swap r> + swap r> ?do 2dup c@ swap c!
|
||||||
|
1- swap 1- swap loop 2drop ;
|
||||||
|
: move r> 2dup > if r> cmove else r> cmove> then ;
|
||||||
|
: negate 0 swap - ;
|
||||||
|
: recurse last @ , ; immediate
|
||||||
|
: _lit" r> dup 1 + swap dup c@ dup rot + compsize + 0 compsize - and >r ;
|
||||||
|
84 last @ link>flags c! ( Set STRING flag )
|
||||||
|
: _compile" [char] " word count dup >r dup >r c, here r> cmove r> allot
|
||||||
|
compsize here - compmask and allot ; immediate
|
||||||
|
create s"buf 50 allot
|
||||||
|
: s" state @ if ['] _lit" compile, postpone _compile" else
|
||||||
|
[char] " word count >r s"buf r@ cmove s"buf r> then ; immediate
|
||||||
|
: ." postpone s" ['] type compile, ; immediate
|
||||||
|
: _abort" if type abort else drop drop then ;
|
||||||
|
\ : abort" postpone s" ['] _abort" compile, ; immediate
|
||||||
|
: abort" postpone s" ['] _abort" compile, ;
|
||||||
|
: space 20 emit ;
|
||||||
|
: spaces 0 ?do space loop ;
|
||||||
|
: u._ 0 <# #s #> type ;
|
||||||
|
: u. u._ 20 emit ;
|
||||||
|
: u< over over xor 1 31 lshift and if swap then < ;
|
||||||
|
: unloop r> r> r> drop drop >r ;
|
||||||
|
: variable create cellsize allot ;
|
||||||
|
|
||||||
|
( CORE EXT )
|
||||||
|
: 0<> 0= invert ;
|
||||||
|
: 0> 0 > ;
|
||||||
|
: 2>r r> rot >r swap >r >r ;
|
||||||
|
: 2r> r> r> r> rot >r swap ;
|
||||||
|
: 2r@ r> r> r> 2dup >r >r swap rot >r ;
|
||||||
|
: <> = 0= ;
|
||||||
|
: erase 0 ?do dup 0 swap ! 1 + loop drop ;
|
||||||
|
variable span
|
||||||
|
: expect accept span ! ;
|
||||||
|
: false 0 ;
|
||||||
|
: marker create last @ , does> @ dup dp ! @ last ! ;
|
||||||
|
: nip swap drop ;
|
||||||
|
: parse word count ;
|
||||||
|
: true 0 1 - ;
|
||||||
|
: tuck swap over ;
|
||||||
|
: to ' >body state @ if postpone literal [compile] ! else ! then ; immediate
|
||||||
|
\ : value create here ! cellsize allot does> @ ;
|
||||||
|
: value create , last @ link>xt dup w@ 3 - swap w! ;
|
||||||
|
: within over - >r - r> u< ;
|
||||||
|
: .r_ >r dup abs 0 <# #s rot sign #> dup r> swap - spaces type ;
|
||||||
|
: .r .r_ 20 emit ;
|
||||||
|
: u.r_ >r 0 <# #s #> dup r> swap - spaces type ;
|
||||||
|
: u.r .r_ 20 emit ;
|
||||||
|
: u> over over xor 80000000 and if swap then > ;
|
||||||
|
: unused 8000 here - ;
|
||||||
|
: case 0 ; immediate
|
||||||
|
: of ['] over compile, ['] = compile,
|
||||||
|
['] _jz compile, here 4 allot ['] drop compile, ; immediate
|
||||||
|
: endof ['] _jmp compile, here 2 + swap w! here 2 allot ; immediate
|
||||||
|
: endcase ['] drop compile, begin ?dup while here swap w! repeat ; immediate
|
||||||
|
: c" ['] _lit" compile, postpone _compile" ['] drop compile, ['] 1- compile, ; immediate
|
||||||
|
: .( [char] ) word count type ; immediate
|
||||||
|
: :noname align here ['] words @ , [ ;
|
||||||
|
|
||||||
|
( DOUBLE )
|
||||||
|
: d= rot = rot rot = and ;
|
||||||
|
: d0= or 0 = ;
|
||||||
|
: 2constant create swap , , does> dup @ swap cellsize + @ ;
|
||||||
|
|
||||||
|
( STRING )
|
||||||
|
: blank 0 ?do dup bl swap c! 1+ loop drop ;
|
||||||
|
: -trailing dup 0 ?do 2dup + 1- c@ bl = if 1- else leave then loop ;
|
||||||
|
: /string dup >r - swap r> + swap ;
|
||||||
|
|
||||||
|
( TOOLS )
|
||||||
|
: ? @ . ;
|
||||||
|
: .s 3c emit depth ._ 3e emit 20 emit depth 0 ?do depth i - 1 - pick . loop ;
|
||||||
|
: dump 0 ?do i 0f and 0 = if cr dup . then dup c@ 3 .r 1 + loop drop cr ;
|
||||||
|
: forget 20 word find if >link dup dp ! w@ last ! else abort" ?" then ;
|
||||||
|
: .name dup link>name count type space ;
|
||||||
|
: ?newline dup >r link>name c@ dup rot + 1 + dup 4e > if cr else swap then drop r> ;
|
||||||
|
: words 0 last @ begin dup while ?newline .name w@ repeat 2drop ;
|
||||||
|
|
||||||
|
( UTILITY )
|
||||||
|
: at-xy 2 emit swap emit emit ;
|
||||||
|
: page 0 emit ;
|
||||||
|
|
||||||
|
( VERSION STRING )
|
||||||
|
: pfthversion s" pfth 1.03" ;
|
||||||
|
|
||||||
|
create evalmode 0 ,
|
||||||
|
0 value source-id
|
||||||
|
create srcstk0 30 allot
|
||||||
|
srcstk0 value srcstk
|
||||||
|
|
||||||
|
: resetstack depth 0 <
|
||||||
|
if
|
||||||
|
begin depth while 0 repeat
|
||||||
|
else
|
||||||
|
begin depth while drop repeat
|
||||||
|
then
|
||||||
|
;
|
||||||
|
|
||||||
|
: getnumber 2dup >r >r swap dup c@ [char] - =
|
||||||
|
if
|
||||||
|
swap
|
||||||
|
dup 1 <
|
||||||
|
if
|
||||||
|
2drop 2drop r> r> 1
|
||||||
|
else
|
||||||
|
swap 1 + swap 1 -
|
||||||
|
>number dup
|
||||||
|
if
|
||||||
|
2drop 2drop r> r> 1
|
||||||
|
else
|
||||||
|
2drop drop negate 0 r> r> 2drop
|
||||||
|
then
|
||||||
|
then
|
||||||
|
else
|
||||||
|
swap
|
||||||
|
>number dup
|
||||||
|
if
|
||||||
|
2drop 2drop r> r> 1
|
||||||
|
else
|
||||||
|
2drop drop 0 r> r> 2drop
|
||||||
|
then
|
||||||
|
then
|
||||||
|
;
|
||||||
|
|
||||||
|
: compilenumber
|
||||||
|
dup ['] _lit compile, compile,
|
||||||
|
dup ffff 10 lshift and
|
||||||
|
if
|
||||||
|
10 rshift
|
||||||
|
['] _lit compile, compile,
|
||||||
|
['] _lit compile, 10 compile,
|
||||||
|
['] lshift compile,
|
||||||
|
['] or compile,
|
||||||
|
else
|
||||||
|
drop
|
||||||
|
then
|
||||||
|
;
|
||||||
|
|
||||||
|
: _interpret
|
||||||
|
begin
|
||||||
|
20 word dup c@
|
||||||
|
while
|
||||||
|
find dup
|
||||||
|
if
|
||||||
|
state @ =
|
||||||
|
if
|
||||||
|
compile,
|
||||||
|
else
|
||||||
|
execute
|
||||||
|
then
|
||||||
|
else
|
||||||
|
dup rot count getnumber
|
||||||
|
if
|
||||||
|
type ." ?" cr
|
||||||
|
else
|
||||||
|
state @
|
||||||
|
if
|
||||||
|
compilenumber
|
||||||
|
then
|
||||||
|
then
|
||||||
|
then
|
||||||
|
repeat
|
||||||
|
drop
|
||||||
|
;
|
||||||
|
|
||||||
|
: .savesrc ." _savesrc " srcstk0 . srcstk . cr ;
|
||||||
|
: .loadsrc ." _loadsrc " srcstk0 . srcstk . cr ;
|
||||||
|
|
||||||
|
: _savesrc ( .savesrc ) tib srcstk ! #tib @ srcstk 4 + ! >in @ srcstk 8 + ! source-id srcstk 0c + ! srcstk 10 + to srcstk ;
|
||||||
|
: _loadsrc srcstk 10 - to srcstk ( .loadsrc ) srcstk @ to tib srcstk 4 + @ #tib ! srcstk 8 + @ >in ! srcstk 0c + @ to source-id ;
|
||||||
|
: evaluate _savesrc 0 1 - to source-id #tib ! to tib 0 >in ! _interpret _loadsrc ;
|
||||||
|
|
||||||
|
( INTERPRETER )
|
||||||
|
: interpret
|
||||||
|
begin
|
||||||
|
_interpret
|
||||||
|
depth 0 <
|
||||||
|
if
|
||||||
|
." Stack Underflow" cr
|
||||||
|
resetstack
|
||||||
|
else
|
||||||
|
source-id 0 1 - =
|
||||||
|
if
|
||||||
|
_loadsrc
|
||||||
|
\ 0 to source-id
|
||||||
|
else
|
||||||
|
source-id 0=
|
||||||
|
if ." ok" cr then
|
||||||
|
refill
|
||||||
|
then
|
||||||
|
then
|
||||||
|
again
|
||||||
|
;
|
||||||
|
|
||||||
|
decimal
|
||||||
|
interpret
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
+--------------------------------------------------------------------
|
||||||
|
| TERMS OF USE: MIT License
|
||||||
|
+--------------------------------------------------------------------
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files
|
||||||
|
(the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
+------------------------------------------------------------------
|
|
@ -0,0 +1 @@
|
||||||
|
Object "pfth.spin" Interface:
Program: 0 Longs
Variable: 0 Longs
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,62 @@
|
||||||
|
\ primes.4th
|
||||||
|
\
|
||||||
|
\ Example code for kForth
|
||||||
|
\ Copyright (c) 1998 Creative Consulting for Research and Education
|
||||||
|
\
|
||||||
|
|
||||||
|
\ Test for a prime number. Return the largest divisor (< n )
|
||||||
|
\ and a flag indicating whether the number is prime or not.
|
||||||
|
|
||||||
|
: ?prime ( n -- m flag | is n a prime number? )
|
||||||
|
\ if flag is false (0), m is the largest divisor of n
|
||||||
|
abs
|
||||||
|
dup 3 > \ is n > 3 ?
|
||||||
|
if
|
||||||
|
abs
|
||||||
|
dup 2 /mod
|
||||||
|
swap 0=
|
||||||
|
if \ is n divisible by 2 ?
|
||||||
|
nip false
|
||||||
|
else
|
||||||
|
1- \ check for divisibility starting
|
||||||
|
begin \ with n/2 - 1 and counting down
|
||||||
|
2dup mod
|
||||||
|
over 1 >
|
||||||
|
and
|
||||||
|
while
|
||||||
|
1-
|
||||||
|
repeat
|
||||||
|
nip
|
||||||
|
dup 1 <=
|
||||||
|
then
|
||||||
|
else
|
||||||
|
dup 1 > IF drop 1 true ELSE false THEN
|
||||||
|
then
|
||||||
|
;
|
||||||
|
|
||||||
|
: test_prime ( n -- | test for prime number and display result )
|
||||||
|
?prime
|
||||||
|
if
|
||||||
|
." is a prime number" drop
|
||||||
|
else
|
||||||
|
." is NOT prime. Its largest divisor is " .
|
||||||
|
then
|
||||||
|
cr
|
||||||
|
;
|
||||||
|
|
||||||
|
: list_primes ( n -- | list all the prime numbers from 2 to n )
|
||||||
|
abs
|
||||||
|
dup 0>
|
||||||
|
if
|
||||||
|
1+ 2 do
|
||||||
|
i ?prime
|
||||||
|
if
|
||||||
|
i . cr
|
||||||
|
then
|
||||||
|
drop
|
||||||
|
loop
|
||||||
|
else
|
||||||
|
drop
|
||||||
|
then
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
( PROP WORDS)
|
||||||
|
hex
|
||||||
|
|
||||||
|
( REGISTER ACCESS )
|
||||||
|
: cnt@ 1f1 cog@ ;
|
||||||
|
: ina@ 1f2 cog@ ;
|
||||||
|
: outa@ 1f4 cog@ ;
|
||||||
|
: outa! 1f4 cog! ;
|
||||||
|
: dira@ 1f6 cog@ ;
|
||||||
|
: dira! 1f6 cog! ;
|
||||||
|
: clkfreq@ 0 @ ;
|
||||||
|
|
||||||
|
( BIT SETTING AND CLEARING )
|
||||||
|
: dirasetbit dira@ or dira! ;
|
||||||
|
: diraclrbit invert dira@ and dira! ;
|
||||||
|
: outasetbit outa@ or outa! ;
|
||||||
|
: outaclrbit invert outa@ and outa! ;
|
||||||
|
|
||||||
|
( HUBOPS )
|
||||||
|
: cogid ( ... cogid ) 0 0cfc0001 cogx1 ;
|
||||||
|
: locknew ( ... locknum ) 0 0cfc0004 cogx1 ;
|
||||||
|
: lockret ( locknum ... ) 0cfc0005 cogx1 drop ;
|
||||||
|
: cogstop ( cognum ... ) 0c7c0003 cogx1 drop ;
|
||||||
|
: coginit ( codeptr dataptr cognum ... cognum )
|
||||||
|
>r 0e lshift or 2 lshift r> or 0ffc0002 cogx1 ;
|
||||||
|
: cognew ( codeptr dataptr ... cognum ) 8 coginit ;
|
||||||
|
: waitcnt ( count ... count ) f8fc0000 cogx1 ;
|
||||||
|
: reboot 80 0cfc0000 cogx1 ;
|
||||||
|
|
||||||
|
decimal
|
||||||
|
|
||||||
|
( ANS UTILITY )
|
||||||
|
: ms ( msec ... ) cnt@ swap clkfreq@ 1000 / * + waitcnt drop ;
|
||||||
|
|
||||||
|
( ANS TOOLS EXT )
|
||||||
|
: bye reboot ;
|
||||||
|
|
||||||
|
( ENABLE SERIAL OUTPUT )
|
||||||
|
1 30 lshift dup outa! dira!
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
0 value ii 0 value jj
|
||||||
|
0 value KeyAddr 0 value KeyLen
|
||||||
|
create SArray 256 allot \ state array of 256 bytes
|
||||||
|
: KeyArray KeyLen mod KeyAddr ;
|
||||||
|
|
||||||
|
: get_byte + c@ ;
|
||||||
|
: set_byte + c! ;
|
||||||
|
: as_byte 255 and ;
|
||||||
|
: reset_ij 0 TO ii 0 TO jj ;
|
||||||
|
: i_update 1 + as_byte TO ii ;
|
||||||
|
: j_update ii SArray get_byte + as_byte TO jj ;
|
||||||
|
: swap_s_ij
|
||||||
|
jj SArray get_byte
|
||||||
|
ii SArray get_byte jj SArray set_byte
|
||||||
|
ii SArray set_byte
|
||||||
|
;
|
||||||
|
|
||||||
|
: rc4_init ( KeyAddr KeyLen -- )
|
||||||
|
256 min TO KeyLen TO KeyAddr
|
||||||
|
256 0 DO i i SArray set_byte LOOP
|
||||||
|
reset_ij
|
||||||
|
BEGIN
|
||||||
|
ii KeyArray get_byte jj + j_update
|
||||||
|
swap_s_ij
|
||||||
|
ii 255 < WHILE
|
||||||
|
ii i_update
|
||||||
|
REPEAT
|
||||||
|
reset_ij
|
||||||
|
;
|
||||||
|
: rc4_byte
|
||||||
|
ii i_update jj j_update
|
||||||
|
swap_s_ij
|
||||||
|
ii SArray get_byte jj SArray get_byte + as_byte SArray get_byte xor
|
||||||
|
;
|
||||||
|
|
||||||
|
hex
|
||||||
|
create AKey 61 c, 8A c, 63 c, D2 c, FB c,
|
||||||
|
\ create AKey 97 c, 8A c, 99 c, D2 c, FB c,
|
||||||
|
: test cr 0 DO rc4_byte . LOOP cr ;
|
||||||
|
AKey 5 rc4_init
|
||||||
|
2C F9 4C EE DC 5 test \ output should be: F1 38 29 C9 DE
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
0 value ii 0 value jj
|
||||||
|
0 value KeyAddr 0 value KeyLen
|
||||||
|
create SArray 256 allot \ state array of 256 bytes
|
||||||
|
create Results 100 allot
|
||||||
|
: KeyArray KeyLen mod KeyAddr ;
|
||||||
|
|
||||||
|
: get_byte + c@ ;
|
||||||
|
: set_byte + c! ;
|
||||||
|
: as_byte 255 and ;
|
||||||
|
: reset_ij 0 TO ii 0 TO jj ;
|
||||||
|
: i_update 1 + as_byte TO ii ;
|
||||||
|
: j_update ii SArray get_byte + as_byte TO jj ;
|
||||||
|
: swap_s_ij
|
||||||
|
jj SArray get_byte
|
||||||
|
ii SArray get_byte jj SArray set_byte
|
||||||
|
ii SArray set_byte
|
||||||
|
;
|
||||||
|
|
||||||
|
: rc4_init ( KeyAddr KeyLen -- )
|
||||||
|
256 min TO KeyLen TO KeyAddr
|
||||||
|
256 0 DO i i SArray set_byte LOOP
|
||||||
|
reset_ij
|
||||||
|
BEGIN
|
||||||
|
ii KeyArray get_byte jj + j_update
|
||||||
|
swap_s_ij
|
||||||
|
ii 255 < WHILE
|
||||||
|
ii i_update
|
||||||
|
REPEAT
|
||||||
|
reset_ij
|
||||||
|
;
|
||||||
|
: rc4_byte
|
||||||
|
ii i_update jj j_update
|
||||||
|
swap_s_ij
|
||||||
|
ii SArray get_byte jj SArray get_byte + as_byte SArray get_byte xor
|
||||||
|
;
|
||||||
|
|
||||||
|
\ : cnt@ 0 ;
|
||||||
|
|
||||||
|
hex
|
||||||
|
create AKey 61 c, 8a c, 63 c, d2 c, fb c,
|
||||||
|
\ create AKey 97 c, 8a c, 99 c, d2 c, fb c,
|
||||||
|
: test 0 DO rc4_byte Results i + c! LOOP ;
|
||||||
|
: test1 cr 0 do Results i + c@ . loop cr ;
|
||||||
|
: time hex cnt@
|
||||||
|
AKey 5 rc4_init
|
||||||
|
2c f9 4c ee dc 5 test \ output should be: f1 38 29 c9 de
|
||||||
|
cnt@ 5 test1 swap - 13880 / decimal . ." msec" cr ;
|
||||||
|
decimal
|
||||||
|
|
|
@ -0,0 +1,244 @@
|
||||||
|
pfth Version 1.03
|
||||||
|
November 8, 2013
|
||||||
|
Dave Hein
|
||||||
|
(with additions from G. Herzog)
|
||||||
|
|
||||||
|
INTRODUCTION
|
||||||
|
------------
|
||||||
|
|
||||||
|
pfth is an ANS Forth interpreter that runs on the Propeller. It is written in
|
||||||
|
PASM and Forth, and it can be built using the Prop Tool or BST. pfth
|
||||||
|
implements all 133 of the ANS Forth core words, and 38 of the 45 core ext
|
||||||
|
words. pfth will run on any Propeller board that supports the standard serial
|
||||||
|
interface. The default settings of the serial port are 115200 baud, 8 bits, no
|
||||||
|
parity and 1 stop bit.
|
||||||
|
|
||||||
|
After loading and communications is established, use 'words' to verify that the
|
||||||
|
display is correct. The CR word is defined to emit both a carriage return and
|
||||||
|
a line feed. If your terminal displays an extra line you can either disable
|
||||||
|
the linefeed character on your terminal, or re-define CR to only emit a
|
||||||
|
carriage return.
|
||||||
|
|
||||||
|
|
||||||
|
VERSIONS OF SPIN FILES
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
There are four versions of pfth.
|
||||||
|
|
||||||
|
The first version can be used to build stand-alone Forth applications. It is
|
||||||
|
in pfth.spin. In this version, Forth programs are included using the Spin FILE
|
||||||
|
directive.
|
||||||
|
|
||||||
|
A second version interfaces to an SD card and can execute Forth programs on
|
||||||
|
the SD card. This version is in sdpfth.spin. The program is set up for the C3
|
||||||
|
card, but it can be modified to support other cards.
|
||||||
|
|
||||||
|
The third version is named ospfth.spin, and runs under the Spinix operating
|
||||||
|
system. When Spinix starts up pfth it provides information about the SD pins,
|
||||||
|
the current working directory and a parameter list. The OS version of pfth
|
||||||
|
uses this information to initialize the SD card driver and change to the
|
||||||
|
working directory. It includes the file given by the parameter list.
|
||||||
|
|
||||||
|
The final version is called chess.spin, and implements a chess program. After
|
||||||
|
the program is loaded type "chess" to start playing. A move is entered by
|
||||||
|
typing the source and destination postions separated by a "-". As an example,
|
||||||
|
the move "D2-D4" will move the white queen's pawn two spaces ahead.
|
||||||
|
|
||||||
|
|
||||||
|
LEXICON
|
||||||
|
-------
|
||||||
|
|
||||||
|
pfth has over 50 kernel words, with most of them from the ANS core word set.
|
||||||
|
The source code for pfth is contained in pfth.spin, init.fth and other Forth
|
||||||
|
programs included at the end of pfth.spin.
|
||||||
|
|
||||||
|
Two of the non-standard words implemented by pfth are cog@ and cog!. These are
|
||||||
|
are used to read and write cog memory locations. Their main purpose is to
|
||||||
|
access the Prop registers, such as CNT, INA and OUTA.
|
||||||
|
|
||||||
|
Another non-standard word is cogx1, which is used to execute native Prop
|
||||||
|
instructions. The TOS contains the Prop instruction, and the next value on the
|
||||||
|
stack is used for the destination register value. The result of the execution
|
||||||
|
of the instruction is returned on the stack.
|
||||||
|
|
||||||
|
Some other non-standard words are _lit, _gethex, _jz and .x.
|
||||||
|
|
||||||
|
_lit is used to encode literal values.
|
||||||
|
_gethex is used during the boot phase to convert numeric strings to hex values.
|
||||||
|
_jz implements a jump-on-zero primitive.
|
||||||
|
.x is used for debug purposes, and it prints values as 8-digit hex numbers.
|
||||||
|
|
||||||
|
Some of the kernel words are shown below.
|
||||||
|
|
||||||
|
Interpreter Words Math and Logical Words Memory Access
|
||||||
|
----------------- ---------------------- -------------
|
||||||
|
evaluate + !
|
||||||
|
execute - @
|
||||||
|
find * c!
|
||||||
|
word / c@
|
||||||
|
refill mod
|
||||||
|
create and Console I/O
|
||||||
|
: or -----------
|
||||||
|
; xor emit
|
||||||
|
< key
|
||||||
|
= accept
|
||||||
|
Program Termination >
|
||||||
|
------------------- lshift Primitive Words
|
||||||
|
abort rshift ---------------
|
||||||
|
exit _lit
|
||||||
|
quit Variables _gethex
|
||||||
|
--------- _jz
|
||||||
|
Stack Operations #tib .x
|
||||||
|
---------------- tib
|
||||||
|
drop >in Propeller Words
|
||||||
|
pick base ---------------
|
||||||
|
roll dp cog!
|
||||||
|
>r last cog@
|
||||||
|
r> state cogx1
|
||||||
|
depth
|
||||||
|
swap
|
||||||
|
dup
|
||||||
|
|
||||||
|
|
||||||
|
pfth also contains a small number of pre-compiled Forth words written
|
||||||
|
in Forth. These words are here, allot, ",", _jmp and count. The definition
|
||||||
|
of these words is as follows.
|
||||||
|
|
||||||
|
: here dp @ ;
|
||||||
|
: allot dp @ + dp ! ;
|
||||||
|
: , here ! 4 allot ;
|
||||||
|
: _jmp r> @ >r ;
|
||||||
|
: count 0 pick 1 + 1 roll c@ ;
|
||||||
|
|
||||||
|
|
||||||
|
AT START UP
|
||||||
|
-----------
|
||||||
|
|
||||||
|
When pfth starts up, it runs a small boot interpreter that compiles
|
||||||
|
the ANS dictionary contained in init.fth. This file is included in the
|
||||||
|
PASM binary image using the PASM FILE directive. Other Forth source files
|
||||||
|
may be included after init.fth to add additional words and to implement a
|
||||||
|
specific application.
|
||||||
|
|
||||||
|
The boot interpreter can only handle 16-bit hex numbers, so pfth is in the hex
|
||||||
|
mode when first starting up. The boot interpreter has no error handling
|
||||||
|
capability, and is only used to build the initial dictionary. The boot
|
||||||
|
interpreter uses a limited vocabulary consisting of the following 20
|
||||||
|
kernel words.
|
||||||
|
|
||||||
|
dp state _lit _gethex : ; c@ @ ! + = pick roll drop
|
||||||
|
r> >r word find execute refill
|
||||||
|
|
||||||
|
The boot interpreter is shown below in a pseudo-Forth language. The
|
||||||
|
labels (label1), (label2), etc. are actually encoded as PASM labels, but
|
||||||
|
they are shown symbolically in the code below.
|
||||||
|
|
||||||
|
: xboot
|
||||||
|
(label1)
|
||||||
|
20 word 0 pick c@ _jz (label2) ( Get word, refill if empty )
|
||||||
|
find 0 pick _jz (label3) ( Find word, get number if not found )
|
||||||
|
state @ = _jz (label4) ( Go execute if not compile mode or immediate )
|
||||||
|
, _jmp (label1) ( Otherwise, compile and loop again )
|
||||||
|
(label4)
|
||||||
|
execute _jmp (label1) ( Execute and loop again )
|
||||||
|
(label3)
|
||||||
|
drop count _gethex ( Get number )
|
||||||
|
state @ _jz (label1) ( Loop again if not compile mode )
|
||||||
|
_lit _lit , , _jmp (label1) ( Otherwise, compile number and loop again )
|
||||||
|
(label2)
|
||||||
|
drop refill _jmp (label1) ( Refill and loop again )
|
||||||
|
;
|
||||||
|
|
||||||
|
The boot interpreter compiles init.fth, which then runs the main interpreter.
|
||||||
|
The main interpreter performs some error handling by checking for undefined
|
||||||
|
words and stack underflows. It also handles negative numbers and numbers in
|
||||||
|
any base.
|
||||||
|
|
||||||
|
|
||||||
|
SOURCE PROGRAMS
|
||||||
|
---------------
|
||||||
|
|
||||||
|
There are a number of additional Forth source programs included in this
|
||||||
|
distribution that can be run by pfth. Open and read these as text files to
|
||||||
|
learn more details.
|
||||||
|
|
||||||
|
comus.fth - provides a several useful non-standard words that are commonly
|
||||||
|
used.
|
||||||
|
|
||||||
|
starting.fth - contains samples of code from the "Starting Forth" tutorial.
|
||||||
|
|
||||||
|
rc4time.fth - implements the RC4 code included in the Wikipedia Forth entry.
|
||||||
|
It also displays the time required to run the RC4 code.
|
||||||
|
|
||||||
|
i2c.fth - is a Forth implementation of Mike Green's basic_i2c_driver from
|
||||||
|
the OBEX.
|
||||||
|
|
||||||
|
fds.fth - implementes some of the functions from the FullDuplexSerial
|
||||||
|
driver. It uses the binary PASM code from FullDuplexSerial.
|
||||||
|
|
||||||
|
toggle.fth - will start up a cog running the Forth interpreter. It toggles
|
||||||
|
P15, but it can easily be modified to toggle another pin.
|
||||||
|
|
||||||
|
ted.fth - a simple line-oriented text editor based on the ED text editor.
|
||||||
|
|
||||||
|
linux.fth - implements some basic linux commands, such as ls, cat, rm and cp.
|
||||||
|
|
||||||
|
|
||||||
|
STARTING FORTH COGS
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Forth cogs are started with cognew or coginit by specifying the Forth cog image
|
||||||
|
as the execution pointer and a 5-long structure as the data pointer. The
|
||||||
|
5-long structure is defined as follow
|
||||||
|
|
||||||
|
First long: Address of the body of a word that will be executed on startup
|
||||||
|
Second long: Initial value of the stack pointer
|
||||||
|
Third long: Address of the beginning of the stack
|
||||||
|
Fourth long: Initial value of the return stack pointer
|
||||||
|
Fifth long: Address of the beginning the the return stack
|
||||||
|
|
||||||
|
|
||||||
|
CELL SIZE
|
||||||
|
---------
|
||||||
|
|
||||||
|
The cell size for pfth is 32 bits. The words !, @ and "," words access 32-bit
|
||||||
|
values that are 32-bit aligned. Additional words are provide for smaller unit
|
||||||
|
access, such as w! and w@ for word access, and c! and c@ for byte access.
|
||||||
|
|
||||||
|
The compiled list cell size is 16 bits. The compile, word must be used when
|
||||||
|
compiling execution tokens into a list rather than just using the "," word.
|
||||||
|
|
||||||
|
|
||||||
|
DICTIONARY ENTRY FORMAT
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The format for the pfth dictionary entry is shown below. The beginning of a
|
||||||
|
word entry and its body are long-aligned. The link pointer contains the
|
||||||
|
address of the previous word in the dictionary.
|
||||||
|
|
||||||
|
The flags byte contains various flag bits that indicate if the word is an
|
||||||
|
immediate word, a literal number or string, or a jump word. The name length
|
||||||
|
byte and the name string specify the name of the word. It is followed by
|
||||||
|
padding bytes that ensure long alignment.
|
||||||
|
|
||||||
|
The code pointer contains the cog address of the PASM code that is to be
|
||||||
|
executed. The execution token for a word points to this field. The does>
|
||||||
|
pointer contains the hub address of a list of execution tokens that is to be
|
||||||
|
called.
|
||||||
|
|
||||||
|
The body is a variable length field that contains the contents of a variable or
|
||||||
|
the list of execution tokens for a compiled word. The list for a compiled word
|
||||||
|
consists of one execution token per word, and is terminated by a zero-valued
|
||||||
|
word.
|
||||||
|
|
||||||
|
Offset Content Size
|
||||||
|
------ ------- ----
|
||||||
|
0 Link Pointer word
|
||||||
|
2 Flags byte
|
||||||
|
3 Name Length byte
|
||||||
|
4 Name String Len bytes
|
||||||
|
4+Len Padding (-Len) & 3 bytes
|
||||||
|
4+(Len+3)&(-4) Code Pointer word
|
||||||
|
6+(Len+3)&(-4) DOES> Pointer word
|
||||||
|
8+(Len+3)&(-4) Body Variable
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
: cond.name ( link )
|
||||||
|
dup link>flags c@ dup 2 and ( link flag literal )
|
||||||
|
if
|
||||||
|
8 and
|
||||||
|
if
|
||||||
|
.name
|
||||||
|
then
|
||||||
|
else
|
||||||
|
4 and
|
||||||
|
if
|
||||||
|
[char] s emit [char] " emit bl emit
|
||||||
|
else
|
||||||
|
.name
|
||||||
|
then
|
||||||
|
then
|
||||||
|
;
|
||||||
|
|
||||||
|
: seefunc ( xt )
|
||||||
|
>body ( listptr )
|
||||||
|
begin
|
||||||
|
dup w@ ( listptr xt )
|
||||||
|
while
|
||||||
|
dup w@ ( listptr xt )
|
||||||
|
>link .name link>flags c@ dup 2 and ( listptr flags literal )
|
||||||
|
if
|
||||||
|
8 and ( listptr flags jump )
|
||||||
|
if
|
||||||
|
2 + dup dup w@ swap - 2 - 2 / .
|
||||||
|
else
|
||||||
|
2 + dup w@ .
|
||||||
|
then
|
||||||
|
else
|
||||||
|
4 and ( listptr string )
|
||||||
|
if
|
||||||
|
2 + dup count type [char] " emit space
|
||||||
|
dup c@ + 0 2 - and
|
||||||
|
then
|
||||||
|
then
|
||||||
|
compsize + ( listptr+=compsize)
|
||||||
|
repeat
|
||||||
|
drop
|
||||||
|
;
|
||||||
|
|
||||||
|
: see
|
||||||
|
' dup ( xt xt )
|
||||||
|
if
|
||||||
|
dup >flags c@ dup 16 and ( xt flags kernel )
|
||||||
|
if
|
||||||
|
drop
|
||||||
|
drop
|
||||||
|
." Kernel Word"
|
||||||
|
else
|
||||||
|
32 and
|
||||||
|
if
|
||||||
|
drop
|
||||||
|
." Variable"
|
||||||
|
else
|
||||||
|
seefunc
|
||||||
|
then
|
||||||
|
then
|
||||||
|
else
|
||||||
|
drop
|
||||||
|
." ?"
|
||||||
|
then
|
||||||
|
;
|
|
@ -0,0 +1,20 @@
|
||||||
|
: waitcnt begin dup cnt@ - 0< until ;
|
||||||
|
|
||||||
|
: putch 256 or dup + clkfreq@ 9600 /
|
||||||
|
11 >r
|
||||||
|
cnt@
|
||||||
|
begin
|
||||||
|
r> 1- dup >r
|
||||||
|
while
|
||||||
|
rot dup
|
||||||
|
30 lshift
|
||||||
|
outa!
|
||||||
|
1 rshift
|
||||||
|
swap rot dup rot +
|
||||||
|
waitcnt
|
||||||
|
repeat
|
||||||
|
r> 2drop 2drop
|
||||||
|
;
|
||||||
|
|
||||||
|
: test cnt@ 65 putch cnt@ swap - 80 / . ;
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
: STAR 42 EMIT ;
|
||||||
|
: MARGIN CR 30 SPACES ;
|
||||||
|
: BLIP MARGIN STAR ;
|
||||||
|
: STARS 0 DO STAR LOOP ;
|
||||||
|
: BAR MARGIN 5 STARS ;
|
||||||
|
: F BAR BLIP BAR BLIP BLIP CR ;
|
||||||
|
: MULT CR 11 1 DO DUP I * . LOOP DROP ;
|
||||||
|
: TABLE CR 11 1 DO I MULT LOOP ;
|
||||||
|
: TABLE1 CR 11 1 DO 11 1 DO I J * . LOOP CR LOOP ;
|
||||||
|
: DUB 32767 1 DO I . I +LOOP ;
|
||||||
|
: GREET ." Hello, I speak Forth " ;
|
||||||
|
: GIFT ." chocolate" ;
|
||||||
|
: GIVER ." Mum" ;
|
||||||
|
: THANKS CR ." Dear " GIVER ." ,"
|
||||||
|
CR ." Thanks for the " GIFT ." . " ;
|
||||||
|
: EGGSIZE DUP 18 < IF ." reject " ELSE
|
||||||
|
DUP 21 < IF ." small " ELSE
|
||||||
|
DUP 24 < IF ." medium " ELSE
|
||||||
|
DUP 27 < IF ." large " ELSE
|
||||||
|
DUP 30 < IF ." extra large " ELSE
|
||||||
|
." error "
|
||||||
|
THEN THEN THEN THEN THEN DROP ;
|
||||||
|
: FALSE 0 ;
|
||||||
|
: TRUE -1 ;
|
||||||
|
: TEST IF ." non-" THEN ." zero " ;
|
||||||
|
: /CHECK ?DUP IF / THEN ;
|
||||||
|
: UNCOUNT DROP 1 - ;
|
||||||
|
: max-int -1 1 rshift ;
|
||||||
|
: min-int max-int negate 1 - ;
|
||||||
|
: max-uint -1 ;
|
||||||
|
: OUTPUT-TEST
|
||||||
|
." YOU SHOULD SEE THE STANDARD GRAPHIC CHARACTERS:" CR
|
||||||
|
41 BL DO I EMIT LOOP CR
|
||||||
|
61 41 DO I EMIT LOOP CR
|
||||||
|
127 61 DO I EMIT LOOP CR
|
||||||
|
." YOU SHOULD SEE 0-9 SEPARATED BY A SPACE:" CR
|
||||||
|
9 1+ 0 DO I . LOOP CR
|
||||||
|
." YOU SHOULD SEE 0-9 (WITH NO SPACES):" CR
|
||||||
|
57 1+ 48 DO I 0 SPACES EMIT LOOP CR
|
||||||
|
." YOU SHOULD SEE A-G SEPARATED BY A SPACE:" CR
|
||||||
|
71 1+ 65 DO I EMIT SPACE LOOP CR
|
||||||
|
." YOU SHOULD SEE 0-5 SEPARATED BY TWO SPACES:" CR
|
||||||
|
5 1+ 0 DO I 48 + EMIT 2 SPACES LOOP CR
|
||||||
|
." YOU SHOULD SEE TWO SEPARATE LINES:" CR
|
||||||
|
." LINE 1" CR ." LINE 2" CR
|
||||||
|
." YOU SHOULD SEE THE NUMBER RANGES OF SIGNED AND UNSIGNED NUMBERS:" CR
|
||||||
|
." SIGNED: " MIN-INT . MAX-INT . CR
|
||||||
|
." UNSIGNED: " 0 . MAX-UINT U. CR
|
||||||
|
;
|
||||||
|
|
||||||
|
output-test
|
||||||
|
f
|
||||||
|
10 mult
|
||||||
|
table
|
||||||
|
table1
|
||||||
|
dub
|
||||||
|
greet
|
||||||
|
thanks cr
|
||||||
|
17 eggsize cr
|
||||||
|
22 eggsize cr
|
||||||
|
25 eggsize cr
|
||||||
|
28 eggsize cr
|
||||||
|
32 eggsize cr
|
||||||
|
0 test cr
|
||||||
|
1 test cr
|
|
@ -0,0 +1,2 @@
|
||||||
|
: TIME CNT@ 100000 BEGIN 1 - DUP 0 = UNTIL DROP CNT@ SWAP - 8000 / . ;
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
\ ############################################################################
|
||||||
|
\ # toggle.fth - This program starts up a Forth cog that toggles P15
|
||||||
|
\ #
|
||||||
|
\ # Copyright (c) 2012 Dave Hein
|
||||||
|
\ # MIT Licensed
|
||||||
|
\ ############################################################################
|
||||||
|
|
||||||
|
create cogstack 80 allot \ Allocate data stack space
|
||||||
|
create cogreturn 80 allot \ Allocate return stack space
|
||||||
|
create delaycnt 80000000 , \ This variable controls the blink rate
|
||||||
|
|
||||||
|
hex
|
||||||
|
\ This word toggles bit P15 every "delaycnt" cycles
|
||||||
|
: toggle
|
||||||
|
8000 dirasetbit cnt@ \ Set P15 for output and get CNT
|
||||||
|
begin
|
||||||
|
delaycnt @ + waitcnt \ Wait "delaycnt" cycles
|
||||||
|
8000 outasetbit \ Set P15
|
||||||
|
delaycnt @ + waitcnt \ Wait "delaycnt" cycles
|
||||||
|
8000 outaclrbit \ Clear P15
|
||||||
|
again ; \ Repeat forever
|
||||||
|
decimal
|
||||||
|
|
||||||
|
create cogconfig \ Forth cog config structure
|
||||||
|
' toggle >body , \ Get execution token for TOGGLE
|
||||||
|
cogstack , \ Initial value of stack ptr
|
||||||
|
cogstack , \ Empty value for stack ptr
|
||||||
|
cogreturn , \ Initial value of return ptr
|
||||||
|
cogreturn , \ Empty value for return ptr
|
||||||
|
|
||||||
|
\ This word starts a cog running the TOGGLE word
|
||||||
|
: starttoggle forth @ cogconfig cognew ;
|
||||||
|
|
|
@ -0,0 +1,592 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.21
|
||||||
|
' Copyright (c) 2010, 2011
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef LINUX
|
||||||
|
#include "conion.h"
|
||||||
|
#else
|
||||||
|
#include <conio.h>
|
||||||
|
#endif
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "interp.h"
|
||||||
|
#include "opcodes.h"
|
||||||
|
|
||||||
|
#define OP_NONE 0
|
||||||
|
#define OP_UNSIGNED_OBJ_OFFSET 1
|
||||||
|
#define OP_UNSIGNED_VAR_OFFSET 2
|
||||||
|
#define OP_UNSIGNED_LOC_OFFSET 3
|
||||||
|
#define OP_DATA 4
|
||||||
|
#define OP_SIGNED_JMP_OFFSET 5
|
||||||
|
#define OP_MEMORY_OPCODE_WRITE 6
|
||||||
|
#define OP_OBJ_CALL_PAIR 7
|
||||||
|
#define OP_SIGNED_OFFSET 8
|
||||||
|
#define OP_PACKED_LITERAL 9
|
||||||
|
#define OP_BYTE_LITERAL 10
|
||||||
|
#define OP_WORD_LITERAL 11
|
||||||
|
#define OP_NEAR_LONG_LITERAL 12
|
||||||
|
#define OP_LONG_LITERAL 13
|
||||||
|
#define OP_MEMORY_OPCODE 14
|
||||||
|
#define OP_MEMORY_OPCODE_READ 15
|
||||||
|
#define OP_COMPACT_VAR_OFFSET 16
|
||||||
|
#define OP_COMPACT_LOC_OFFSET 17
|
||||||
|
|
||||||
|
extern char *hubram;
|
||||||
|
extern int32_t memsize;
|
||||||
|
extern int32_t symflag;
|
||||||
|
|
||||||
|
extern FILE *tracefile;
|
||||||
|
|
||||||
|
void RemoveCRLF(char *str)
|
||||||
|
{
|
||||||
|
int32_t len = strlen(str);
|
||||||
|
|
||||||
|
if(len == 0) return;
|
||||||
|
|
||||||
|
str += len-1;
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
if (*str != 10 && *str != 13) break;
|
||||||
|
*str-- = 0;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *FindOpcode(int32_t pcurr, int32_t *ops_format, int32_t mode)
|
||||||
|
{
|
||||||
|
int32_t opcode;
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
opcode = BYTE(pcurr);
|
||||||
|
|
||||||
|
if (mode)
|
||||||
|
{
|
||||||
|
opcode &= 0x7f;
|
||||||
|
if (opcode >= 0x40)
|
||||||
|
opcode += 0xe0 - 0x40;
|
||||||
|
else if (opcode >= 0x20)
|
||||||
|
opcode &= 0x78;
|
||||||
|
else if (opcode >= 0x08)
|
||||||
|
opcode &= 0x7c;
|
||||||
|
else
|
||||||
|
opcode &= 0x7e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (opcode >= 0x40 && opcode <= 0x7f) opcode &= 0x63;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; optable[i].opname; i++)
|
||||||
|
{
|
||||||
|
if (opcode != optable[i].opcode) continue;
|
||||||
|
if (mode == 0 || (optable[i].opform >> 5) >= 2) break;
|
||||||
|
}
|
||||||
|
if (!optable[i].opname) return 0;
|
||||||
|
*ops_format = optable[i].opform;
|
||||||
|
return optable[i].opname;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char objname[100][20];
|
||||||
|
extern int32_t methodnum[100];
|
||||||
|
extern int32_t methodlev;
|
||||||
|
|
||||||
|
char *FindChar(char *str, int32_t val)
|
||||||
|
{
|
||||||
|
while (*str && *str != val)
|
||||||
|
str++;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRet(void)
|
||||||
|
{
|
||||||
|
if (!symflag) return;
|
||||||
|
methodlev--;
|
||||||
|
fprintf(tracefile, "return %s\n\n", objname[methodlev]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char linebuf[200];
|
||||||
|
|
||||||
|
void ProcessCall(int32_t subnum, int32_t mode)
|
||||||
|
{
|
||||||
|
int32_t methnum = 0;
|
||||||
|
FILE *infile;
|
||||||
|
|
||||||
|
if (!symflag) return;
|
||||||
|
|
||||||
|
infile = fopen(objname[methodlev], "r");
|
||||||
|
if (mode)
|
||||||
|
{
|
||||||
|
methodlev++;
|
||||||
|
strcpy(objname[methodlev], objname[methodlev-1]);
|
||||||
|
}
|
||||||
|
methodnum[methodlev] = subnum;
|
||||||
|
if (!infile) return;
|
||||||
|
|
||||||
|
// Count pubs
|
||||||
|
while (fgets(linebuf, 200, infile))
|
||||||
|
{
|
||||||
|
if (strncmp(linebuf, "PUB", 3) == 0 || strncmp(linebuf, "pub", 3) == 0)
|
||||||
|
{
|
||||||
|
methnum++;
|
||||||
|
if (methnum == subnum)
|
||||||
|
{
|
||||||
|
fprintf(tracefile, "call %s:%s\n", objname[methodlev], linebuf);
|
||||||
|
fclose(infile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(infile);
|
||||||
|
infile = fopen(objname[methodlev], "r");
|
||||||
|
|
||||||
|
// Count pris
|
||||||
|
while (fgets(linebuf, 200, infile))
|
||||||
|
{
|
||||||
|
if (strncmp(linebuf, "PRI", 3) == 0 || strncmp(linebuf, "pri", 3) == 0)
|
||||||
|
{
|
||||||
|
methnum++;
|
||||||
|
if (methnum == subnum)
|
||||||
|
{
|
||||||
|
fprintf(tracefile, "call %s:%s\n", objname[methodlev], linebuf);
|
||||||
|
fclose(infile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessObjCall(int32_t objnum, int32_t subnum)
|
||||||
|
{
|
||||||
|
int32_t mode = 0;
|
||||||
|
int32_t methnum = 0;
|
||||||
|
int32_t commentmode = 0;
|
||||||
|
int32_t found = 0;
|
||||||
|
FILE *infile;
|
||||||
|
|
||||||
|
if (!symflag) return;
|
||||||
|
|
||||||
|
infile = fopen(objname[methodlev], "r");
|
||||||
|
methodlev++;
|
||||||
|
strcpy(objname[methodlev], objname[methodlev-1]);
|
||||||
|
methodnum[methodlev] = subnum;
|
||||||
|
if (!infile) return;
|
||||||
|
|
||||||
|
// Count pubs and pris
|
||||||
|
while (fgets(linebuf, 200, infile))
|
||||||
|
{
|
||||||
|
if (linebuf[0] == '}')
|
||||||
|
{
|
||||||
|
commentmode--;
|
||||||
|
if (commentmode < 0) commentmode = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (linebuf[0] == '{')
|
||||||
|
{
|
||||||
|
if (*FindChar(linebuf, '}') == 0)
|
||||||
|
commentmode++;
|
||||||
|
}
|
||||||
|
if (commentmode) continue;
|
||||||
|
if (strncmp(linebuf, "PUB", 3) == 0 || strncmp(linebuf, "pub", 3) == 0 ||
|
||||||
|
strncmp(linebuf, "PRI", 3) == 0 || strncmp(linebuf, "pri", 3) == 0)
|
||||||
|
{
|
||||||
|
methnum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(infile);
|
||||||
|
infile = fopen(objname[methodlev], "r");
|
||||||
|
|
||||||
|
// Count objs
|
||||||
|
commentmode = 0;
|
||||||
|
while (fgets(linebuf, 200, infile))
|
||||||
|
{
|
||||||
|
if (linebuf[0] == '}')
|
||||||
|
{
|
||||||
|
commentmode--;
|
||||||
|
if (commentmode < 0) commentmode = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (linebuf[0] == '{')
|
||||||
|
{
|
||||||
|
if (*FindChar(linebuf, '}') == 0)
|
||||||
|
commentmode++;
|
||||||
|
}
|
||||||
|
if (commentmode) continue;
|
||||||
|
if (mode == 0)
|
||||||
|
{
|
||||||
|
if (strncmp(linebuf, "OBJ", 3) == 0 || strncmp(linebuf, "obj", 3) == 0)
|
||||||
|
mode = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
methnum++;
|
||||||
|
if (linebuf[0] != ' ') break;
|
||||||
|
if (methnum == objnum)
|
||||||
|
{
|
||||||
|
char *ptr1;
|
||||||
|
char *ptr2;
|
||||||
|
int32_t num;
|
||||||
|
|
||||||
|
// Locate filename
|
||||||
|
ptr1 = FindChar(linebuf, '"');
|
||||||
|
if (*ptr1)
|
||||||
|
ptr1++;
|
||||||
|
ptr2 = FindChar(ptr1, '"');
|
||||||
|
if (*ptr2) ptr2--;
|
||||||
|
else
|
||||||
|
ptr2 = ptr1;
|
||||||
|
num = ptr2 - ptr1 + 1;
|
||||||
|
if (num < 1) num = 1;
|
||||||
|
memcpy(objname[methodlev], ptr1, num);
|
||||||
|
objname[methodlev][num] = 0;
|
||||||
|
if (symflag == 2)
|
||||||
|
strcat(objname[methodlev], ".spn");
|
||||||
|
else
|
||||||
|
strcat(objname[methodlev], ".spin");
|
||||||
|
fclose(infile);
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
fclose(infile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProcessCall(subnum, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetOpIndex(int opcode);
|
||||||
|
static int GetExOpIndex(int opcode);
|
||||||
|
|
||||||
|
void PrintOp(SpinVarsT *spinvars)
|
||||||
|
{
|
||||||
|
long pcurr = spinvars->pcurr;
|
||||||
|
int32_t opcode;
|
||||||
|
int32_t opform = 0;
|
||||||
|
char *opstr;
|
||||||
|
int exop1, exop2;
|
||||||
|
int32_t val;
|
||||||
|
int32_t operand;
|
||||||
|
char *regop[] = {"ldreg", "streg", "exreg", "??reg"};
|
||||||
|
char *regname[] = {"par", "cnt", "ina", "inb", "outa", "outb", "dira",
|
||||||
|
"dirb", "ctra", "ctrb", "frqa", "frqb", "phsa", "phsb", "vcfg", "vscl"};
|
||||||
|
char bytestr[40], symstr[100];
|
||||||
|
|
||||||
|
if (spinvars->state != 1) return;
|
||||||
|
|
||||||
|
opcode = BYTE(pcurr);
|
||||||
|
exop1 = GetOpIndex(opcode);
|
||||||
|
exop2 = -1;
|
||||||
|
opstr = FindOpcode(pcurr, &opform, 0);
|
||||||
|
|
||||||
|
memset(bytestr, ' ', 40);
|
||||||
|
bytestr[20] = 0;
|
||||||
|
sprintf(bytestr, "%4.4x %2.2x", (unsigned int)pcurr, opcode);
|
||||||
|
symstr[0] = 0;
|
||||||
|
|
||||||
|
switch (opform & 0x1f)
|
||||||
|
{
|
||||||
|
case OP_NONE:
|
||||||
|
strcpy(symstr, opstr);
|
||||||
|
if (strncmp(opstr, "ret", 3) == 0)
|
||||||
|
ProcessRet();
|
||||||
|
pcurr++;
|
||||||
|
break;
|
||||||
|
case OP_UNSIGNED_OBJ_OFFSET:
|
||||||
|
case OP_UNSIGNED_VAR_OFFSET:
|
||||||
|
case OP_UNSIGNED_LOC_OFFSET:
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
if (operand & 0x80)
|
||||||
|
{
|
||||||
|
operand = ((operand & 0x7f) << 8) | BYTE(pcurr+2);
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x", BYTE(pcurr+1), BYTE(pcurr+2));
|
||||||
|
pcurr += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x", BYTE(pcurr+1));
|
||||||
|
pcurr += 2;
|
||||||
|
}
|
||||||
|
sprintf(symstr, "%s $%x", opstr, operand);
|
||||||
|
break;
|
||||||
|
case OP_DATA:
|
||||||
|
sprintf(symstr, "%s - ******** TBD ********", opstr);
|
||||||
|
pcurr++;
|
||||||
|
break;
|
||||||
|
case OP_SIGNED_OFFSET:
|
||||||
|
case OP_SIGNED_JMP_OFFSET:
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
if (operand & 0x80)
|
||||||
|
{
|
||||||
|
operand = ((operand & 0x7f) << 8) | BYTE(pcurr+2);
|
||||||
|
operand = (operand << 17) >> 17;
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x", BYTE(pcurr+1), BYTE(pcurr+2));
|
||||||
|
pcurr += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
operand = (operand << 25) >> 25;
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x", BYTE(pcurr+1));
|
||||||
|
pcurr += 2;
|
||||||
|
}
|
||||||
|
sprintf(symstr, "%s %d", opstr, operand);
|
||||||
|
break;
|
||||||
|
case OP_MEMORY_OPCODE_READ:
|
||||||
|
case OP_MEMORY_OPCODE_WRITE:
|
||||||
|
operand = (BYTE(pcurr+1) >> 5) & 3;
|
||||||
|
opstr = regop[operand];
|
||||||
|
if (operand == 2) opform |= 1 << 5;
|
||||||
|
operand = (BYTE(pcurr+1) & 31);
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x", BYTE(pcurr+1));
|
||||||
|
if (operand <= 15)
|
||||||
|
{
|
||||||
|
sprintf(symstr, "%s $%3.3x", opstr, operand + 0x1e0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(symstr, "%s %s", opstr, regname[operand-16]);
|
||||||
|
}
|
||||||
|
pcurr += 2;
|
||||||
|
break;
|
||||||
|
case OP_OBJ_CALL_PAIR:
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x", BYTE(pcurr+1), BYTE(pcurr+2));
|
||||||
|
sprintf(symstr, "%s %d %d", opstr, BYTE(pcurr+1), BYTE(pcurr+2));
|
||||||
|
ProcessObjCall(BYTE(pcurr+1), BYTE(pcurr+2));
|
||||||
|
pcurr += 3;
|
||||||
|
break;
|
||||||
|
case OP_PACKED_LITERAL:
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
val = 2 << (operand & 31);
|
||||||
|
if (operand & 0x20) val--;
|
||||||
|
if (operand & 0x40) val = ~val;
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x", operand);
|
||||||
|
sprintf(symstr, "%s $%x", opstr, val);
|
||||||
|
pcurr += 2;
|
||||||
|
break;
|
||||||
|
case OP_BYTE_LITERAL:
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x", operand);
|
||||||
|
sprintf(symstr, "%s %d", opstr, operand);
|
||||||
|
if (strcmp(opstr, "call") == 0)
|
||||||
|
ProcessCall(operand, 1);
|
||||||
|
pcurr += 2;
|
||||||
|
break;
|
||||||
|
case OP_WORD_LITERAL:
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
operand = (operand << 8) | BYTE(pcurr+2);
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x", BYTE(pcurr+1), BYTE(pcurr+2));
|
||||||
|
sprintf(symstr, "%s %d", opstr, operand);
|
||||||
|
pcurr += 3;
|
||||||
|
break;
|
||||||
|
case OP_NEAR_LONG_LITERAL:
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
operand = (operand << 8) | BYTE(pcurr+2);
|
||||||
|
operand = (operand << 8) | BYTE(pcurr+3);
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x %2.2x",
|
||||||
|
BYTE(pcurr+1), BYTE(pcurr+2), BYTE(pcurr+3));
|
||||||
|
sprintf(symstr, "%s %d", opstr, operand);
|
||||||
|
pcurr += 4;
|
||||||
|
break;
|
||||||
|
case OP_LONG_LITERAL:
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
operand = (operand << 8) | BYTE(pcurr+2);
|
||||||
|
operand = (operand << 8) | BYTE(pcurr+3);
|
||||||
|
operand = (operand << 8) | BYTE(pcurr+4);
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x %2.2x %2.2x",
|
||||||
|
BYTE(pcurr+1), BYTE(pcurr+2), BYTE(pcurr+3), BYTE(pcurr+4));
|
||||||
|
sprintf(symstr, "%s %d", opstr, operand);
|
||||||
|
pcurr += 5;
|
||||||
|
break;
|
||||||
|
case OP_MEMORY_OPCODE:
|
||||||
|
sprintf(symstr, "%s - ******** TBD ********", opstr);
|
||||||
|
pcurr++;
|
||||||
|
break;
|
||||||
|
case OP_COMPACT_VAR_OFFSET:
|
||||||
|
case OP_COMPACT_LOC_OFFSET:
|
||||||
|
operand = opcode & 0x1c;
|
||||||
|
sprintf(symstr, "%s $%x", opstr, operand);
|
||||||
|
pcurr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((opform >> 5) == 1)
|
||||||
|
{
|
||||||
|
char *loadstr = "";
|
||||||
|
opcode = BYTE(pcurr);
|
||||||
|
exop2 = GetExOpIndex(opcode);
|
||||||
|
if (opcode & 0x80)
|
||||||
|
{
|
||||||
|
loadstr = "load";
|
||||||
|
opcode &= 0x7f;
|
||||||
|
}
|
||||||
|
opstr = FindOpcode(pcurr, &opform, 1);
|
||||||
|
if (opcode != 0x02)
|
||||||
|
{
|
||||||
|
sprintf(symstr + strlen(symstr), " %s %s", opstr, loadstr);
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x", BYTE(pcurr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
operand = BYTE(pcurr+1);
|
||||||
|
if (operand < 0x80)
|
||||||
|
{
|
||||||
|
operand = (operand << 25) >> 25;
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x",
|
||||||
|
BYTE(pcurr), BYTE(pcurr+1));
|
||||||
|
pcurr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
operand = (operand << 8) | BYTE(pcurr+2);
|
||||||
|
operand = (operand << 17) >> 17;
|
||||||
|
sprintf(bytestr + strlen(bytestr), " %2.2x %2.2x %2.2x",
|
||||||
|
BYTE(pcurr), BYTE(pcurr+1), BYTE(pcurr+2));
|
||||||
|
pcurr += 2;
|
||||||
|
}
|
||||||
|
sprintf(symstr + strlen(symstr), " %s %d %s", opstr, operand, loadstr);
|
||||||
|
}
|
||||||
|
pcurr++;
|
||||||
|
}
|
||||||
|
bytestr[strlen(bytestr)] = ' ';
|
||||||
|
fprintf(tracefile, "%s %s\n", bytestr, symstr);
|
||||||
|
//fprintf(tracefile, "%s [%2d,%2d] %s\n", bytestr, exop1, exop2, symstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int opcount[256];
|
||||||
|
static int exopcount[27][45];
|
||||||
|
|
||||||
|
static int GetExOpIndex(int opcode)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
opcode &= 0x7f;
|
||||||
|
if (opcode >= 0x40)
|
||||||
|
index = (opcode & 0x1f) + 13;
|
||||||
|
else if (opcode >= 0x20)
|
||||||
|
index = (opcode >> 3) + 5;
|
||||||
|
else if (opcode >= 0x02)
|
||||||
|
index = (opcode >> 2) + 1;
|
||||||
|
else
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
static int GetOpIndex(int opcode)
|
||||||
|
{
|
||||||
|
int index = -1;
|
||||||
|
|
||||||
|
if (opcode == 0x26)
|
||||||
|
index = 0;
|
||||||
|
else if ((opcode >= 0x40 && opcode <= 0x7f) && (opcode & 3) == 2)
|
||||||
|
index = ((opcode - 0x40) >> 7) + 1;
|
||||||
|
else if ((opcode >= 0x80 && opcode < 0xe0) && (opcode & 3) == 2)
|
||||||
|
index = ((opcode - 0x80) >> 2) + 3;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetStats(void)
|
||||||
|
{
|
||||||
|
memset(opcount, 0, 256 * 4);
|
||||||
|
memset(exopcount, 0, 27 * 45 * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CountOp(SpinVarsT *spinvars)
|
||||||
|
{
|
||||||
|
int pcurr = spinvars->pcurr;
|
||||||
|
int opcode = BYTE(pcurr++);
|
||||||
|
int opindex, exopindex;
|
||||||
|
|
||||||
|
if (opcode >= 0x40 && opcode <= 0x7f) opcode &= 0x63;
|
||||||
|
opcount[opcode]++;
|
||||||
|
opindex = GetOpIndex(opcode);
|
||||||
|
if (opindex < 0) return;
|
||||||
|
if (opcode >= 0x80 && ((opcode >> 2) & 3))
|
||||||
|
{
|
||||||
|
opcode = BYTE(pcurr++);
|
||||||
|
if (opcode & 0x80) pcurr++;
|
||||||
|
}
|
||||||
|
opcode = BYTE(pcurr);
|
||||||
|
exopindex = GetExOpIndex(opcode);
|
||||||
|
exopcount[opindex][exopindex]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintStats(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int opcode;
|
||||||
|
int opindex;
|
||||||
|
int exop, k;
|
||||||
|
char *exname;
|
||||||
|
char *opname;
|
||||||
|
static char *exopname[13] = {
|
||||||
|
"store", "repeat", "repeats", "randf", "randr", "sexb", "sexw",
|
||||||
|
"postclr", "postset", "preinc", "postinc", "predec", "postdec"};
|
||||||
|
static unsigned char exopcode[13] = { 0x00, 0x02, 0x06, 0x08,
|
||||||
|
0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x28, 0x30, 0x38};
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
if (opcount[i] == 0) continue;
|
||||||
|
opcode = i;
|
||||||
|
if (opcode >= 0x40 && opcode <= 0x7f) opcode &= 0x63;
|
||||||
|
|
||||||
|
for (j = 0; optable[j].opname; j++)
|
||||||
|
{
|
||||||
|
if (opcode == optable[j].opcode) break;
|
||||||
|
}
|
||||||
|
opname = optable[j].opname;
|
||||||
|
opindex = GetOpIndex(i);
|
||||||
|
if (opindex >= 0)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 45; j++)
|
||||||
|
{
|
||||||
|
if (exopcount[opindex][j] == 0) continue;
|
||||||
|
if (j < 13)
|
||||||
|
{
|
||||||
|
exop = exopcode[j];
|
||||||
|
exname = exopname[j];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exop = j - 13 + 0xe0;
|
||||||
|
for (k = 0; optable[k].opname; k++)
|
||||||
|
{
|
||||||
|
if (exop == optable[k].opcode) break;
|
||||||
|
}
|
||||||
|
exname = optable[k].opname;
|
||||||
|
}
|
||||||
|
fprintf(tracefile, "%10d, %2.2x:%2.2x, %s:%s\n",
|
||||||
|
exopcount[opindex][j], i, exop, opname, exname);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(tracefile, "%10d, %2.2x, %s\n", opcount[i], i, opname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,3 @@
|
||||||
|
void ResetStats(void);
|
||||||
|
void CountOp(SpinVarsT *spinvars);
|
||||||
|
void PrintStats(void);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,920 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
' Author: Dave Hein
|
||||||
|
' Version 0.75
|
||||||
|
' Copyright (c) 2010 - 2014
|
||||||
|
' See end of file for terms of use.
|
||||||
|
'******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#ifdef LINUX
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "conion.h"
|
||||||
|
#else
|
||||||
|
#include <conio.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#endif
|
||||||
|
#include "interp.h"
|
||||||
|
#include "rom.h"
|
||||||
|
#include "spindebug.h"
|
||||||
|
#include "eeprom.h"
|
||||||
|
|
||||||
|
// Define system I/O addresses and commands
|
||||||
|
//#define SYS_COMMAND 0x12340000
|
||||||
|
//#define SYS_LOCKNUM 0x12340002
|
||||||
|
//#define SYS_PARM 0x12340004
|
||||||
|
//#define SYS_DEBUG 0x12340008
|
||||||
|
|
||||||
|
#define SYS_CON_PUTCH 1
|
||||||
|
#define SYS_CON_GETCH 2
|
||||||
|
#define SYS_FILE_OPEN 3
|
||||||
|
#define SYS_FILE_CLOSE 4
|
||||||
|
#define SYS_FILE_READ 5
|
||||||
|
#define SYS_FILE_WRITE 6
|
||||||
|
#define SYS_FILE_OPENDIR 7
|
||||||
|
#define SYS_FILE_CLOSEDIR 8
|
||||||
|
#define SYS_FILE_READDIR 9
|
||||||
|
#define SYS_FILE_SEEK 10
|
||||||
|
#define SYS_FILE_TELL 11
|
||||||
|
#define SYS_FILE_REMOVE 12
|
||||||
|
#define SYS_FILE_CHDIR 13
|
||||||
|
#define SYS_FILE_GETCWD 14
|
||||||
|
#define SYS_FILE_MKDIR 15
|
||||||
|
#define SYS_FILE_GETMOD 16
|
||||||
|
#define SYS_EXTMEM_READ 17
|
||||||
|
#define SYS_EXTMEM_WRITE 18
|
||||||
|
#define SYS_EXTMEM_ALLOC 19
|
||||||
|
|
||||||
|
#define GCC_REG_BASE 0
|
||||||
|
|
||||||
|
static char rootdir[100];
|
||||||
|
char *hubram;
|
||||||
|
char *extram[4];
|
||||||
|
int32_t extmemsize[4];
|
||||||
|
uint32_t extmembase[4];
|
||||||
|
int32_t extmemnum = 0;
|
||||||
|
char lockstate[8];
|
||||||
|
char lockalloc[8];
|
||||||
|
|
||||||
|
char objname[100][20];
|
||||||
|
int32_t methodnum[100];
|
||||||
|
int32_t methodlev = 0;
|
||||||
|
|
||||||
|
int32_t printflag = 0;
|
||||||
|
int32_t symflag = 0;
|
||||||
|
int32_t pasmspin = 0;
|
||||||
|
int32_t profile = 0;
|
||||||
|
int32_t memsize = 64;
|
||||||
|
int32_t cycleaccurate = 0;
|
||||||
|
int32_t loopcount = 0;
|
||||||
|
int32_t proptwo = 0;
|
||||||
|
int32_t baudrate = 0;
|
||||||
|
int32_t pin_val = -1;
|
||||||
|
int32_t gdbmode = 0;
|
||||||
|
int32_t eeprom = 0;
|
||||||
|
int32_t debugmode = 0;
|
||||||
|
int32_t printbreak = 0;
|
||||||
|
|
||||||
|
FILE *logfile = NULL;
|
||||||
|
FILE *tracefile = NULL;
|
||||||
|
FILE *cmdfile = NULL;
|
||||||
|
|
||||||
|
PasmVarsT PasmVars[8];
|
||||||
|
|
||||||
|
void PrintOp(SpinVarsT *spinvars);
|
||||||
|
void ExecuteOp(SpinVarsT *spinvars);
|
||||||
|
char *FindChar(char *str, int32_t val);
|
||||||
|
void Debug(void);
|
||||||
|
int32_t RunProp(int32_t maxloops);
|
||||||
|
void gdb(void);
|
||||||
|
|
||||||
|
void spinsim_exit(int32_t exitcode)
|
||||||
|
{
|
||||||
|
restore_console_io();
|
||||||
|
exit(exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Spinsim Version 0.75\n");
|
||||||
|
fprintf(stderr, "usage: spinsim [options] file\n");
|
||||||
|
fprintf(stderr, "The options are as follows:\n");
|
||||||
|
fprintf(stderr, " -v# Set verbosity level\n");
|
||||||
|
//fprintf(stderr, " -l List executed instructions\n");
|
||||||
|
fprintf(stderr, " -l <filename> List executed instructions to <filename>\n");
|
||||||
|
fprintf(stderr, " -p Use PASM Spin interpreter\n");
|
||||||
|
fprintf(stderr, " -# Execute # instructions\n");
|
||||||
|
fprintf(stderr, " -P Profile Spin opcode usage\n");
|
||||||
|
fprintf(stderr, " -m# Set the hub memory size to # K-bytes\n");
|
||||||
|
//fprintf(stderr, " -c Enable cycle-accurate mode for pasm cogs\n");
|
||||||
|
fprintf(stderr, " -t Enable the Prop 2 mode\n");
|
||||||
|
fprintf(stderr, " -b# Enable the serial port and set the baudrate to # (default 115200)\n");
|
||||||
|
fprintf(stderr, " -gdb Operate as a GDB target over stdin/stdout\n");
|
||||||
|
fprintf(stderr, " -L <filename> Log GDB remote comm to <filename>\n");
|
||||||
|
fprintf(stderr, " -r <filename> Replay GDB session from <filename>\n");
|
||||||
|
//fprintf(stderr, " -x# Set the external memory size to # K-bytes\n");
|
||||||
|
fprintf(stderr, " -e Use eeprom.dat\n");
|
||||||
|
fprintf(stderr, " -d Use debugger\n");
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void putchx(int32_t val)
|
||||||
|
{
|
||||||
|
putchar(val);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t getchx(void)
|
||||||
|
{
|
||||||
|
uint8_t val = 0;
|
||||||
|
// GCC compiler issues warning for ignored fread return value
|
||||||
|
if(fread(&val, 1, 1, cmdfile /*stdin*/))
|
||||||
|
if (val == 10) val = 13;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *FindExtMem(uint32_t addr, int32_t num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *ptr = 0;
|
||||||
|
uint32_t addr1 = addr + num - 1;
|
||||||
|
uint32_t curraddr, curraddr1;
|
||||||
|
|
||||||
|
//fprintf(stderr, "FindExtMem(%d, %d)\n", addr, num);
|
||||||
|
|
||||||
|
for (i = 0; i < extmemnum; i++)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "i = %d\n", i);
|
||||||
|
curraddr = extmembase[i];
|
||||||
|
curraddr1 = curraddr + extmemsize[i] - 1;
|
||||||
|
if (curraddr <= addr && addr <= curraddr1)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "1: %d %d %d\n", addr, curraddr, curraddr1);
|
||||||
|
//fprintf(stderr, "2: %d %d %d\n", addr1, curraddr, curraddr1);
|
||||||
|
if (curraddr <= addr1 && addr1 <= curraddr1)
|
||||||
|
ptr = extram[i] + addr - extmembase[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This routine prevents us from calling kbhit too often. This improves
|
||||||
|
// the performance of the simulator when calling kbhit in a tight loop.
|
||||||
|
int kbhit1(void)
|
||||||
|
{
|
||||||
|
static int last = 0;
|
||||||
|
|
||||||
|
if (loopcount - last < 6000) return 0;
|
||||||
|
last = loopcount;
|
||||||
|
return kbhit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckCommand(void)
|
||||||
|
{
|
||||||
|
int32_t parm;
|
||||||
|
int32_t command = WORD(SYS_COMMAND);
|
||||||
|
FILE *stream;
|
||||||
|
DIR *pdir;
|
||||||
|
struct dirent *pdirent;
|
||||||
|
|
||||||
|
if (!command) return;
|
||||||
|
|
||||||
|
parm = LONG(SYS_PARM);
|
||||||
|
|
||||||
|
if (command == SYS_CON_PUTCH)
|
||||||
|
{
|
||||||
|
if (parm == 13)
|
||||||
|
putchx(10);
|
||||||
|
else
|
||||||
|
putchx(parm);
|
||||||
|
}
|
||||||
|
else if (command == SYS_CON_GETCH)
|
||||||
|
{
|
||||||
|
if (kbhit1())
|
||||||
|
parm = getch();
|
||||||
|
else
|
||||||
|
parm = -1;
|
||||||
|
LONG(SYS_PARM) = parm;
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_OPEN)
|
||||||
|
{
|
||||||
|
char *fname;
|
||||||
|
char *fmode;
|
||||||
|
|
||||||
|
fname = (char *)&BYTE(LONG(parm));
|
||||||
|
fmode = (char *)&BYTE(LONG(parm+4));
|
||||||
|
stream = fopen(fname, fmode);
|
||||||
|
LONG(SYS_PARM) = (long)stream;
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_CLOSE)
|
||||||
|
{
|
||||||
|
if (parm) fclose((FILE *)(long)parm);
|
||||||
|
LONG(SYS_PARM) = 0;
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_READ)
|
||||||
|
{
|
||||||
|
int32_t num;
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
|
if (!parm) LONG(SYS_PARM) = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream = (FILE *)(long)LONG(parm);
|
||||||
|
buffer = (char *)&BYTE(LONG(parm+4));
|
||||||
|
num = LONG(parm+8);
|
||||||
|
LONG(SYS_PARM) = fread(buffer, 1, num, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_WRITE)
|
||||||
|
{
|
||||||
|
int32_t num;
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
|
if (!parm) LONG(SYS_PARM) = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream = (FILE *)(long)LONG(parm);
|
||||||
|
buffer = (char *)&BYTE(LONG(parm+4));
|
||||||
|
num = LONG(parm+8);
|
||||||
|
LONG(SYS_PARM) = fwrite(buffer, 1, num, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_OPENDIR)
|
||||||
|
{
|
||||||
|
char *dname = ".";
|
||||||
|
|
||||||
|
pdir = opendir(dname);
|
||||||
|
LONG(SYS_PARM) = (long)pdir;
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_CLOSEDIR)
|
||||||
|
{
|
||||||
|
if (parm) closedir((DIR *)(long)parm);
|
||||||
|
LONG(SYS_PARM) = 0;
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_READDIR)
|
||||||
|
{
|
||||||
|
int32_t *buffer;
|
||||||
|
pdir = (DIR *)(long)LONG(parm);
|
||||||
|
buffer = (int32_t *)&BYTE(LONG(parm+4));
|
||||||
|
if (!pdir) LONG(SYS_PARM) = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdirent = readdir(pdir);
|
||||||
|
if (pdirent)
|
||||||
|
{
|
||||||
|
#ifdef LINUX
|
||||||
|
FILE *infile;
|
||||||
|
int32_t d_size = 0;
|
||||||
|
int32_t d_attr = 0;
|
||||||
|
#if 0
|
||||||
|
int32_t d_type = pdirent->d_type;
|
||||||
|
|
||||||
|
if (d_type & DT_DIR) d_attr |= 0x10;
|
||||||
|
if (d_type & S_IXUSR) d_attr |= 0x20;
|
||||||
|
if (!(d_type & S_IWUSR)) d_attr |= 0x01;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((infile = fopen(pdirent->d_name, "r")))
|
||||||
|
{
|
||||||
|
fseek(infile, 0, SEEK_END);
|
||||||
|
d_size = ftell(infile);
|
||||||
|
fclose(infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[0] = d_size;
|
||||||
|
buffer[1] = d_attr;
|
||||||
|
#else
|
||||||
|
buffer[0] = pdirent->d_size;
|
||||||
|
buffer[1] = pdirent->d_attr;
|
||||||
|
#endif
|
||||||
|
strcpy((char *)&buffer[2], pdirent->d_name);
|
||||||
|
}
|
||||||
|
LONG(SYS_PARM) = (long)pdirent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_SEEK)
|
||||||
|
{
|
||||||
|
int32_t offset, whence;
|
||||||
|
stream = (FILE *)(long)LONG(parm);
|
||||||
|
offset = LONG(parm+4);
|
||||||
|
whence = LONG(parm+8);
|
||||||
|
LONG(SYS_PARM) = fseek(stream, offset, whence);
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_TELL)
|
||||||
|
{
|
||||||
|
stream = (FILE *)(long)parm;
|
||||||
|
LONG(SYS_PARM) = ftell(stream);
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_REMOVE)
|
||||||
|
{
|
||||||
|
char *fname = (char *)&BYTE(parm);
|
||||||
|
LONG(SYS_PARM) = remove(fname);
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_CHDIR)
|
||||||
|
{
|
||||||
|
char *path = (char *)&BYTE(parm);
|
||||||
|
char fullpath[200];
|
||||||
|
char *ptr;
|
||||||
|
if (path[0] == '/')
|
||||||
|
{
|
||||||
|
strcpy(fullpath, rootdir);
|
||||||
|
strcat(fullpath, path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcpy(fullpath, path);
|
||||||
|
|
||||||
|
ptr = fullpath;
|
||||||
|
#ifndef LINUX
|
||||||
|
while (*ptr)
|
||||||
|
{
|
||||||
|
if (*ptr == '/') *ptr = 0x5c;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
parm = chdir(fullpath);
|
||||||
|
LONG(SYS_PARM) = parm;
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_GETCWD)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
char *str = (char *)&BYTE(LONG(parm));
|
||||||
|
int32_t num = LONG(parm+4);
|
||||||
|
ptr = getcwd(str, num);
|
||||||
|
LONG(SYS_PARM) = LONG(parm);
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_MKDIR)
|
||||||
|
{
|
||||||
|
//char *fname = (char *)&BYTE(parm);
|
||||||
|
#ifdef LINUX
|
||||||
|
#if 0
|
||||||
|
LONG(SYS_PARM) = mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
LONG(SYS_PARM) = mkdir(fname);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (command == SYS_FILE_GETMOD)
|
||||||
|
{
|
||||||
|
char *fname = (char *)&BYTE(parm);
|
||||||
|
int32_t attrib = -1;
|
||||||
|
|
||||||
|
pdir = opendir(".");
|
||||||
|
while (pdir)
|
||||||
|
{
|
||||||
|
pdirent = readdir(pdir);
|
||||||
|
if (!pdirent) break;
|
||||||
|
if (strcmp(pdirent->d_name, fname) == 0)
|
||||||
|
{
|
||||||
|
#ifdef LINUX
|
||||||
|
#if 0
|
||||||
|
int32_t d_type = pdirent->d_type;
|
||||||
|
attrib = 0;
|
||||||
|
if (d_type & DT_DIR) attrib |= 0x10;
|
||||||
|
if (d_type & S_IXUSR) attrib |= 0x20;
|
||||||
|
if (!(d_type & S_IWUSR)) attrib |= 0x01;
|
||||||
|
#else
|
||||||
|
attrib = 0;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
attrib = pdirent->d_attr;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pdir) closedir(pdir);
|
||||||
|
LONG(SYS_PARM) = attrib;
|
||||||
|
}
|
||||||
|
else if (command == SYS_EXTMEM_READ)
|
||||||
|
{
|
||||||
|
uint32_t extaddr = (uint32_t)LONG(parm);
|
||||||
|
char *hubaddr = (char *)&BYTE(LONG(parm+4));
|
||||||
|
int32_t num = LONG(parm+8);
|
||||||
|
char *extmemptr = FindExtMem(extaddr, num);
|
||||||
|
if (extmemptr)
|
||||||
|
{
|
||||||
|
memcpy(hubaddr, extmemptr, num);
|
||||||
|
LONG(SYS_PARM) = num;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LONG(SYS_PARM) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (command == SYS_EXTMEM_WRITE)
|
||||||
|
{
|
||||||
|
uint32_t extaddr = (int32_t)LONG(parm);
|
||||||
|
char *hubaddr = (char *)&BYTE(LONG(parm+4));
|
||||||
|
int32_t num = LONG(parm+8);
|
||||||
|
char *extmemptr = FindExtMem(extaddr, num);
|
||||||
|
if (extmemptr)
|
||||||
|
{
|
||||||
|
memcpy(extmemptr, hubaddr, num);
|
||||||
|
LONG(SYS_PARM) = num;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LONG(SYS_PARM) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (command == SYS_EXTMEM_ALLOC)
|
||||||
|
{
|
||||||
|
uint32_t extaddr = (int32_t)LONG(parm);
|
||||||
|
int32_t num = LONG(parm+4);
|
||||||
|
uint32_t extaddr1 = extaddr + num - 1;
|
||||||
|
|
||||||
|
if (num <= 0 || extmemnum >= 4) num = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t curraddr, curraddr1;
|
||||||
|
for (i = 0; i < extmemnum; i++)
|
||||||
|
{
|
||||||
|
curraddr = extmembase[i];
|
||||||
|
curraddr1 = curraddr + extmemsize[i] - 1;
|
||||||
|
if (curraddr <= extaddr && extaddr <= curraddr1) break;
|
||||||
|
if (curraddr <= extaddr1 && extaddr1 <= curraddr1) break;
|
||||||
|
if (extaddr <= curraddr && curraddr <= extaddr1) break;
|
||||||
|
if (extaddr <= curraddr1 && curraddr1 <= extaddr1) break;
|
||||||
|
}
|
||||||
|
if (i != extmemnum) num = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extram[extmemnum] = malloc(num);
|
||||||
|
if (extram[extmemnum] == 0) num = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extmemsize[extmemnum] = num;
|
||||||
|
extmembase[extmemnum] = extaddr;
|
||||||
|
extmemnum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LONG(SYS_PARM) = num;
|
||||||
|
}
|
||||||
|
WORD(SYS_COMMAND) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CheckSerialIn(void)
|
||||||
|
{
|
||||||
|
static int state = 0;
|
||||||
|
static int count = 0;
|
||||||
|
static int val;
|
||||||
|
|
||||||
|
if (state == 0)
|
||||||
|
{
|
||||||
|
if (kbhit1())
|
||||||
|
{
|
||||||
|
val = getch();
|
||||||
|
if (val == 0x1d) return 1;
|
||||||
|
val |= 0x300;
|
||||||
|
if (proptwo)
|
||||||
|
count = 80000000 / baudrate;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = LONG(0) / baudrate;
|
||||||
|
count >>= 2;
|
||||||
|
}
|
||||||
|
//if (!proptwo) count >>= 2;
|
||||||
|
pin_val &= 0x7fffffff;
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (--count <= 0)
|
||||||
|
{
|
||||||
|
if (++state > 11)
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pin_val = (pin_val & 0x7fffffff) | ((val & 1) << 31);
|
||||||
|
val >>= 1;
|
||||||
|
#if 0
|
||||||
|
count = LONG(0) / baudrate;
|
||||||
|
if (!proptwo) count >>= 2;
|
||||||
|
#endif
|
||||||
|
if (proptwo)
|
||||||
|
count = 80000000 / baudrate;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = LONG(0) / baudrate;
|
||||||
|
count >>= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSerialOut(void)
|
||||||
|
{
|
||||||
|
int txbit = 0;
|
||||||
|
static int val;
|
||||||
|
static int state = -2;
|
||||||
|
static int count;
|
||||||
|
//static int txbit0 = 0;
|
||||||
|
|
||||||
|
txbit = (pin_val >> 30) & 1;
|
||||||
|
|
||||||
|
//if (txbit != txbit0) fprintf(stderr, "txbit = %d, loopcount = %d\n", txbit, loopcount);
|
||||||
|
//txbit0 = txbit;
|
||||||
|
|
||||||
|
|
||||||
|
if (state == -2)
|
||||||
|
{
|
||||||
|
if (txbit)
|
||||||
|
{
|
||||||
|
state = -1;
|
||||||
|
//fprintf(stderr, "Start Serial\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == -1)
|
||||||
|
{
|
||||||
|
if (!txbit)
|
||||||
|
{
|
||||||
|
val = 0;
|
||||||
|
state = 0;
|
||||||
|
#if 0
|
||||||
|
count = LONG(0) / baudrate;
|
||||||
|
if (!proptwo) count >>= 2;
|
||||||
|
#endif
|
||||||
|
if (proptwo)
|
||||||
|
count = 80000000 / baudrate;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = LONG(0) / baudrate;
|
||||||
|
count >>= 2;
|
||||||
|
}
|
||||||
|
count += count >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (--count <= 0)
|
||||||
|
{
|
||||||
|
if (state > 7)
|
||||||
|
{
|
||||||
|
state = -1;
|
||||||
|
#if 1
|
||||||
|
if (val == 13)
|
||||||
|
putchx(10);
|
||||||
|
else
|
||||||
|
putchx(val);
|
||||||
|
#else
|
||||||
|
printf("<%2.2x>\n", val);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "%d", txbit);
|
||||||
|
val |= txbit << state;
|
||||||
|
#if 0
|
||||||
|
count = LONG(0) / baudrate;
|
||||||
|
if (!proptwo) count >>= 2;
|
||||||
|
#endif
|
||||||
|
if (proptwo)
|
||||||
|
count = 80000000 / baudrate;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = LONG(0) / baudrate;
|
||||||
|
count >>= 2;
|
||||||
|
}
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintStack(SpinVarsT *spinvars)
|
||||||
|
{
|
||||||
|
int32_t dcurr = spinvars->dcurr;
|
||||||
|
printf("PrintStack: %4.4x %8.8x %8.8x %8.8x\n",
|
||||||
|
dcurr, LONG(dcurr-4), LONG(dcurr-8), LONG(dcurr-12));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *bootfile;
|
||||||
|
|
||||||
|
void RebootProp(void)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
int32_t dbase;
|
||||||
|
char *ptr;
|
||||||
|
FILE *infile;
|
||||||
|
|
||||||
|
if (!proptwo) memset(hubram, 0, 32768);
|
||||||
|
memset(lockstate, 0, 8);
|
||||||
|
memset(lockalloc, 0, 8);
|
||||||
|
|
||||||
|
chdir(rootdir);
|
||||||
|
|
||||||
|
if(!gdbmode && eeprom){
|
||||||
|
EEPromCopy(hubram);
|
||||||
|
} else
|
||||||
|
if(!gdbmode){
|
||||||
|
infile = fopen(bootfile, "rb");
|
||||||
|
|
||||||
|
if (infile == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not open %s\n", bootfile);
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = fread(hubram, 1, 32768, infile);
|
||||||
|
fclose(infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy in the ROM contents
|
||||||
|
if (!proptwo)
|
||||||
|
{
|
||||||
|
memcpy(hubram + 32768, romdata, 32768);
|
||||||
|
dbase = WORD(10);
|
||||||
|
LONG(dbase-8) = 0xfff9ffff;
|
||||||
|
LONG(dbase-4) = 0xfff9ffff;
|
||||||
|
LONG(dbase) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WORD(SYS_COMMAND) = 0;
|
||||||
|
WORD(SYS_LOCKNUM) = 1;
|
||||||
|
lockalloc[0] = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) PasmVars[i].state = 0;
|
||||||
|
|
||||||
|
if (pasmspin)
|
||||||
|
{
|
||||||
|
if (proptwo)
|
||||||
|
StartPasmCog2(&PasmVars[0], 0, 0x0e00, 0);
|
||||||
|
else
|
||||||
|
StartPasmCog(&PasmVars[0], 0x0004, 0xf004, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
StartCog((SpinVarsT *)&PasmVars[0].mem[0x1e0], 4, 0);
|
||||||
|
|
||||||
|
if(!gdbmode){
|
||||||
|
strcpy(objname[0], "xxx");
|
||||||
|
if (bootfile)
|
||||||
|
strcpy(objname[1], bootfile);
|
||||||
|
else
|
||||||
|
strcpy(objname[1], "");
|
||||||
|
ptr = FindChar(objname[1], '.');
|
||||||
|
if (*ptr)
|
||||||
|
{
|
||||||
|
*ptr = 0;
|
||||||
|
if (symflag && strcmp(ptr + 1, "bin") == 0)
|
||||||
|
symflag = 2;
|
||||||
|
}
|
||||||
|
if (symflag == 2)
|
||||||
|
strcat(objname[1], ".spn");
|
||||||
|
else
|
||||||
|
strcat(objname[1], ".spin");
|
||||||
|
methodnum[0] = 1;
|
||||||
|
methodnum[1] = 1;
|
||||||
|
methodlev = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//LONG(SYS_DEBUG) = printflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
int step_chip(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int state;
|
||||||
|
int runflag = 0;
|
||||||
|
int breakflag = 0;
|
||||||
|
SpinVarsT *spinvars;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
state = PasmVars[i].state;
|
||||||
|
PasmVars[i].printflag = (LONG(SYS_DEBUG) >> (i*4)) & 15;
|
||||||
|
if (state & 4)
|
||||||
|
{
|
||||||
|
if (PasmVars[i].printflag && state == 5)
|
||||||
|
{
|
||||||
|
if (!proptwo)
|
||||||
|
{
|
||||||
|
fprintf(tracefile, "Cog %d: ", i);
|
||||||
|
DebugPasmInstruction(&PasmVars[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proptwo)
|
||||||
|
{
|
||||||
|
breakflag = ExecutePasmInstruction2(&PasmVars[i]);
|
||||||
|
if (PasmVars[i].printflag && state == 5)
|
||||||
|
fprintf(tracefile, "\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExecutePasmInstruction(&PasmVars[i]);
|
||||||
|
if (PasmVars[i].printflag && state == 5) printf("\n");
|
||||||
|
}
|
||||||
|
if (!breakflag &&
|
||||||
|
!(printbreak && PasmVars[i].printflag && state == 5))
|
||||||
|
runflag = 1;
|
||||||
|
}
|
||||||
|
else if (state)
|
||||||
|
{
|
||||||
|
spinvars = (SpinVarsT *)&PasmVars[i].mem[0x1e0];
|
||||||
|
if (PasmVars[i].printflag && state == 1)
|
||||||
|
{
|
||||||
|
int32_t dcurr = spinvars->dcurr;
|
||||||
|
fprintf(tracefile, "Cog %d: %4.4x %8.8x - ", i, dcurr, LONG(dcurr - 4));
|
||||||
|
PrintOp(spinvars);
|
||||||
|
}
|
||||||
|
if (profile) CountOp(spinvars);
|
||||||
|
ExecuteOp(spinvars);
|
||||||
|
runflag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loopcount++;
|
||||||
|
return runflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
char *fname = 0;
|
||||||
|
int32_t i;
|
||||||
|
int32_t maxloops = -1;
|
||||||
|
|
||||||
|
tracefile = stdout;
|
||||||
|
ptr = getcwd(rootdir, 100);
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[i], "-l") == 0){
|
||||||
|
if (i+1 == argc || argv[i+1][0] == '-')
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Trace file not specified\n");
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
if (!printflag) printflag = 0xffffffff;
|
||||||
|
i++;
|
||||||
|
tracefile = fopen(argv[i], "wt");
|
||||||
|
if(!tracefile){
|
||||||
|
fprintf(stderr, "Unable to open trace file %s.\n", argv[i]);
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[i], "-t") == 0)
|
||||||
|
{
|
||||||
|
proptwo = 1;
|
||||||
|
pasmspin = 1;
|
||||||
|
memsize = 256;
|
||||||
|
cycleaccurate = 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "-p") == 0)
|
||||||
|
{
|
||||||
|
pasmspin = 1;
|
||||||
|
cycleaccurate = 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "-s") == 0)
|
||||||
|
symflag = 1;
|
||||||
|
else if (strcmp(argv[i], "-P") == 0)
|
||||||
|
profile = 1;
|
||||||
|
else if (strncmp(argv[i], "-m", 2) == 0)
|
||||||
|
{
|
||||||
|
sscanf(&argv[i][2], "%d", &memsize);
|
||||||
|
}
|
||||||
|
else if (strncmp(argv[i], "-b", 2) == 0)
|
||||||
|
{
|
||||||
|
pasmspin = 1;
|
||||||
|
cycleaccurate = 1;
|
||||||
|
if (argv[i][2] == 0)
|
||||||
|
baudrate = 115200;
|
||||||
|
else
|
||||||
|
sscanf(&argv[i][2], "%d", &baudrate);
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "-gdb") == 0)
|
||||||
|
{
|
||||||
|
gdbmode = 1;
|
||||||
|
cycleaccurate = 1;
|
||||||
|
pasmspin = 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "-L") == 0)
|
||||||
|
{
|
||||||
|
logfile = fopen(argv[++i], "wt");
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "-r") == 0)
|
||||||
|
{
|
||||||
|
cmdfile = fopen(argv[++i], "rt");
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "-e") == 0)
|
||||||
|
{
|
||||||
|
eeprom = 1;
|
||||||
|
}
|
||||||
|
else if (strncmp(argv[i], "-v", 2) == 0)
|
||||||
|
{
|
||||||
|
if (argv[i][2])
|
||||||
|
{
|
||||||
|
sscanf(&argv[i][2], "%x", &printflag);
|
||||||
|
if (!argv[i][3])
|
||||||
|
printflag *= 0x11111111;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printflag = 0xffffffff;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "-d") == 0)
|
||||||
|
{
|
||||||
|
debugmode = 1;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
else if (strncmp(argv[i], "-x", 2) == 0)
|
||||||
|
{
|
||||||
|
sscanf(&argv[i][2], "%d", &extmemsize);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (argv[i][0] == '-' && argv[i][1] >= '0' && argv[i][1] <= '9')
|
||||||
|
sscanf(argv[i] + 1, "%d", &maxloops);
|
||||||
|
else if (argv[i][0] == '-')
|
||||||
|
usage();
|
||||||
|
else if (!fname)
|
||||||
|
fname = argv[i];
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eeprom)
|
||||||
|
EEPromInit(fname);
|
||||||
|
|
||||||
|
if(!cmdfile) cmdfile = stdin;
|
||||||
|
|
||||||
|
// Check the hub memory size and allocate it
|
||||||
|
if (memsize < 32)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Specified memory size is too small\n");
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
if (memsize < 64) memsize = 64;
|
||||||
|
memsize <<= 10; // Multiply it by 1024
|
||||||
|
hubram = malloc(memsize + 16 + 3);
|
||||||
|
if (!hubram)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Specified memory size is too large\n");
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
// Make sure it's long aligned
|
||||||
|
#ifdef __LP64__
|
||||||
|
hubram = (char *)(((uint64_t)hubram) & 0xfffffffffffffffc);
|
||||||
|
#else
|
||||||
|
hubram = (char *)(((uint32_t)hubram) & 0xfffffffc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LONG(SYS_DEBUG) = printflag;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Check the ext memory size and allocate it if non-zero
|
||||||
|
if (extmemsize < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid external memory size\n");
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
else if (extmemsize)
|
||||||
|
{
|
||||||
|
extmemsize <<= 10; // Multiply it by 1024
|
||||||
|
extram = malloc(extmemsize);
|
||||||
|
if (!extram)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Specified external memory size is too large\n");
|
||||||
|
spinsim_exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (profile) ResetStats();
|
||||||
|
|
||||||
|
bootfile = fname;
|
||||||
|
|
||||||
|
if (!fname && !gdbmode && !eeprom) usage();
|
||||||
|
|
||||||
|
RebootProp();
|
||||||
|
initialize_console_io();
|
||||||
|
if (gdbmode)
|
||||||
|
gdb();
|
||||||
|
else if (debugmode)
|
||||||
|
Debug();
|
||||||
|
else
|
||||||
|
RunProp(maxloops);
|
||||||
|
restore_console_io();
|
||||||
|
if (eeprom) EEPromClose();
|
||||||
|
if (profile) PrintStats();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| TERMS OF USE: MIT License |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|
||||||
|
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|
||||||
|
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|
||||||
|
|is furnished to do so, subject to the following conditions: |
|
||||||
|
| |
|
||||||
|
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
|
||||||
|
| |
|
||||||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|
||||||
|
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
||||||
|
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
||||||
|
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
||||||
|
+------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
*/
|
|
@ -0,0 +1,13 @@
|
||||||
|
int step_chip(void);
|
||||||
|
int CheckSerialIn(void);
|
||||||
|
void CheckCommand(void);
|
||||||
|
void putchx(int32_t val);
|
||||||
|
void CheckSerialOut(void);
|
||||||
|
void spinsim_exit(int32_t exitcode);
|
||||||
|
|
||||||
|
#define WAIT_CNT 01
|
||||||
|
#define WAIT_MULT 02
|
||||||
|
#define WAIT_PIN 03
|
||||||
|
#define WAIT_HUB 16
|
||||||
|
#define WAIT_CACHE 17
|
||||||
|
|
Loading…
Reference in New Issue