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