summaryrefslogtreecommitdiff
path: root/410user
diff options
context:
space:
mode:
authorHanjie Wu <hanjiew@andrew.cmu.edu>2023-04-18 02:21:10 -0400
committerHanjie Wu <hanjiew@andrew.cmu.edu>2023-04-18 02:21:10 -0400
commitc71294cdd3581c3738d24ffd65414f8644a1094d (patch)
treec86245d50fad9eee4163dbba169bd1839edbf88f /410user
initial commit
Diffstat (limited to '410user')
-rw-r--r--410user/crt0.c19
-rw-r--r--410user/exec2obj.c208
-rw-r--r--410user/inc/410_tests.h77
-rw-r--r--410user/inc/asm_style.h126
-rw-r--r--410user/inc/assert.h69
-rw-r--r--410user/inc/cond.h18
-rw-r--r--410user/inc/malloc.h17
-rw-r--r--410user/inc/mutex.h15
-rw-r--r--410user/inc/rand.h35
-rw-r--r--410user/inc/rwlock.h20
-rw-r--r--410user/inc/sem.h16
-rw-r--r--410user/inc/stdarg.h18
-rw-r--r--410user/inc/stdbool.h15
-rw-r--r--410user/inc/stddef.h12
-rw-r--r--410user/inc/stdint.h114
-rw-r--r--410user/inc/thread.h26
-rw-r--r--410user/inc/types.h23
-rw-r--r--410user/libRNG/mt19937int.c97
-rw-r--r--410user/libRNG/user.mk6
-rw-r--r--410user/libmalloc/malloc.c639
-rw-r--r--410user/libmalloc/memlib.c72
-rw-r--r--410user/libmalloc/memlib.h13
-rw-r--r--410user/libmalloc/user.mk7
-rw-r--r--410user/libsimics/simics.S14
-rw-r--r--410user/libsimics/simics.h84
-rw-r--r--410user/libsimics/simics_c.c61
-rw-r--r--410user/libsimics/user.mk10
-rw-r--r--410user/libstdio/doprnt.c646
-rw-r--r--410user/libstdio/doprnt.h34
-rw-r--r--410user/libstdio/doscan.c181
-rw-r--r--410user/libstdio/doscan.h30
-rw-r--r--410user/libstdio/hexdump.c71
-rw-r--r--410user/libstdio/printf.c97
-rw-r--r--410user/libstdio/putchar.c31
-rw-r--r--410user/libstdio/puts.c14
-rw-r--r--410user/libstdio/sprintf.c104
-rw-r--r--410user/libstdio/sscanf.c65
-rw-r--r--410user/libstdio/stdio.h46
-rw-r--r--410user/libstdio/user.mk16
-rw-r--r--410user/libstdlib/abs.c27
-rw-r--r--410user/libstdlib/atol.c9
-rw-r--r--410user/libstdlib/ctype.c91
-rw-r--r--410user/libstdlib/ctype.h37
-rw-r--r--410user/libstdlib/exit.c15
-rw-r--r--410user/libstdlib/qsort.c170
-rw-r--r--410user/libstdlib/rand.c62
-rw-r--r--410user/libstdlib/stdlib.h30
-rw-r--r--410user/libstdlib/strtol.c68
-rw-r--r--410user/libstdlib/strtoul.c62
-rw-r--r--410user/libstdlib/user.mk17
-rw-r--r--410user/libstring/memcmp.c53
-rw-r--r--410user/libstring/memset.c34
-rw-r--r--410user/libstring/rindex.c35
-rw-r--r--410user/libstring/strcat.c38
-rw-r--r--410user/libstring/strchr.c35
-rw-r--r--410user/libstring/strcmp.c55
-rw-r--r--410user/libstring/strcpy.c45
-rw-r--r--410user/libstring/strcspn.c64
-rw-r--r--410user/libstring/strdup.c31
-rw-r--r--410user/libstring/string.h57
-rw-r--r--410user/libstring/strlen.c45
-rw-r--r--410user/libstring/strncat.c64
-rw-r--r--410user/libstring/strncmp.c38
-rw-r--r--410user/libstring/strncpy.c51
-rw-r--r--410user/libstring/strpbrk.c54
-rw-r--r--410user/libstring/strrchr.c35
-rw-r--r--410user/libstring/strspn.c57
-rw-r--r--410user/libstring/strstr.c37
-rw-r--r--410user/libstring/strtok.c86
-rw-r--r--410user/libstring/user.mk27
-rw-r--r--410user/libtest/report.c98
-rw-r--r--410user/libtest/report.h109
-rw-r--r--410user/libtest/test.c0
-rw-r--r--410user/libtest/test.h52
-rw-r--r--410user/libtest/testasm.S82
-rw-r--r--410user/libtest/user.mk6
-rw-r--r--410user/libthrgrp/thrgrp.c201
-rw-r--r--410user/libthrgrp/thrgrp.h71
-rw-r--r--410user/libthrgrp/user.mk7
-rw-r--r--410user/libx86/bcopy.S135
-rw-r--r--410user/libx86/bzero.S47
-rw-r--r--410user/libx86/gccisms.c346
-rw-r--r--410user/libx86/user.mk11
-rw-r--r--410user/progs/ack.c56
-rw-r--r--410user/progs/actual_wait.c131
-rw-r--r--410user/progs/bg.c39
-rw-r--r--410user/progs/bistromath.c7711
-rw-r--r--410user/progs/cat.c30
-rw-r--r--410user/progs/cho.c103
-rw-r--r--410user/progs/cho2.c108
-rw-r--r--410user/progs/cho_variant.c171
-rw-r--r--410user/progs/chow.c142
-rw-r--r--410user/progs/ck1.c26
-rw-r--r--410user/progs/coolness.c26
-rw-r--r--410user/progs/deschedule_hang.c32
-rw-r--r--410user/progs/exec_basic.c33
-rw-r--r--410user/progs/exec_basic_helper.c25
-rw-r--r--410user/progs/exec_nonexist.c31
-rw-r--r--410user/progs/fib.c49
-rw-r--r--410user/progs/fork_bomb.c27
-rw-r--r--410user/progs/fork_exit_bomb.c41
-rw-r--r--410user/progs/fork_test1.c41
-rw-r--r--410user/progs/fork_wait.c46
-rw-r--r--410user/progs/fork_wait_bomb.c50
-rw-r--r--410user/progs/getpid_test1.c34
-rw-r--r--410user/progs/halt_test.c26
-rw-r--r--410user/progs/idle.c14
-rw-r--r--410user/progs/init.c28
-rw-r--r--410user/progs/knife.c43
-rw-r--r--410user/progs/loader_test1.c94
-rw-r--r--410user/progs/loader_test2.c273
-rw-r--r--410user/progs/make_crash.c50
-rw-r--r--410user/progs/make_crash_helper.c41
-rw-r--r--410user/progs/mem_eat_test.c58
-rw-r--r--410user/progs/mem_permissions.c98
-rw-r--r--410user/progs/merchant.c59
-rw-r--r--410user/progs/minclone_many.S177
-rw-r--r--410user/progs/minclone_mem.S78
-rw-r--r--410user/progs/new_pages.c95
-rw-r--r--410user/progs/new_shell.c27
-rw-r--r--410user/progs/peon.c35
-rw-r--r--410user/progs/print_basic.c27
-rw-r--r--410user/progs/progs.mk15
-rw-r--r--410user/progs/readline_basic.c25
-rw-r--r--410user/progs/register_test.S172
-rw-r--r--410user/progs/remove_pages_test1.c63
-rw-r--r--410user/progs/remove_pages_test2.c60
-rw-r--r--410user/progs/score.c146
-rw-r--r--410user/progs/shell.c276
-rw-r--r--410user/progs/slaughter.c144
-rw-r--r--410user/progs/sleep_test1.c32
-rw-r--r--410user/progs/stack_test1.c47
-rw-r--r--410user/progs/swexn_basic_test.c77
-rw-r--r--410user/progs/swexn_cookie_monster.c85
-rw-r--r--410user/progs/swexn_dispatch.c55
-rw-r--r--410user/progs/swexn_rampage.c96
-rw-r--r--410user/progs/swexn_regs.c65
-rw-r--r--410user/progs/swexn_stands_for_swextensible.c58
-rw-r--r--410user/progs/swexn_uninstall_test.c60
-rw-r--r--410user/progs/wait_getpid.c48
-rw-r--r--410user/progs/wild_test1.c31
-rw-r--r--410user/progs/work.c58
-rw-r--r--410user/progs/yield_desc_mkrun.c68
-rw-r--r--410user/user.mk60
144 files changed, 17776 insertions, 0 deletions
diff --git a/410user/crt0.c b/410user/crt0.c
new file mode 100644
index 0000000..abe8c50
--- /dev/null
+++ b/410user/crt0.c
@@ -0,0 +1,19 @@
+/* @file crt0.c
+ * @brief The 15-410 userland C runtime setup function
+ *
+ * @note The build infrastructure "knows" that _main is the entrypoint
+ * function and will do the right thing as a result.
+ */
+
+#include <stdlib.h>
+#include <syscall.h>
+#include <assert.h>
+
+extern int main(int argc, char *argv[]);
+extern void install_autostack(void * stack_high, void * stack_low);
+
+void _main(int argc, char *argv[], void *stack_high, void *stack_low)
+{
+ install_autostack(stack_high, stack_low);
+ exit(main(argc, argv));
+}
diff --git a/410user/exec2obj.c b/410user/exec2obj.c
new file mode 100644
index 0000000..80c1a57
--- /dev/null
+++ b/410user/exec2obj.c
@@ -0,0 +1,208 @@
+#include "410kern/inc/exec2obj.h"
+#include <stdio.h>
+#include <string.h>
+
+#define STABS 0
+
+void print_usage() {
+ fprintf(stderr, "Usage: exec2obj <file>...\n");
+ fprintf(stderr, "Creates a .s file containing a const char array for each file\n");
+ fprintf(stderr, "given as an argument. Each array is initialized to the contents\n");
+ fprintf(stderr, "of that file. A table of contents is also created. Look at\n");
+ fprintf(stderr, "exec2obj.h for more information.\n\n");
+}
+
+char header[] =
+#if STABS
+"\t.file\t\"user_apps.c\"\n"
+"\t.stabs\t\"/home/gghartma/15-410/proj2/\",100,0,0,.Ltext0\n"
+"\t.stabs\t\"user_apps.c\",100,0,0,.Ltext0\n"
+#endif
+"\t.text\n"
+".Ltext0:\n"
+#if STABS
+"\t.stabs\t\"gcc2_compiled.\",60,0,0,0\n"
+"\t.stabs\t\"int:t(0,1)=r(0,1);-2147483648;2147483647;\",128,0,0,0\n"
+"\t.stabs\t\"char:t(0,2)=r(0,2);0;127;\",128,0,0,0\n"
+"\t.stabs\t\"long int:t(0,3)=r(0,3);-2147483648;2147483647;\",128,0,0,0\n"
+"\t.stabs\t\"unsigned int:t(0,4)=r(0,4);0000000000000;0037777777777;\",128,0,0,0\n"
+"\t.stabs\t\"long unsigned int:t(0,5)=r(0,5);0000000000000;0037777777777;\",128,0,0,0\n"
+"\t.stabs\t\"long long int:t(0,6)=@s64;r(0,6);01000000000000000000000;0777777777777777777777;\",128,0,0,0\n"
+"\t.stabs\t\"long long unsigned int:t(0,7)=@s64;r(0,7);0000000000000;01777777777777777777777;\",128,0,0,0\n"
+"\t.stabs\t\"short int:t(0,8)=@s16;r(0,8);-32768;32767;\",128,0,0,0\n"
+"\t.stabs\t\"short unsigned int:t(0,9)=@s16;r(0,9);0;65535;\",128,0,0,0\n"
+"\t.stabs\t\"signed char:t(0,10)=@s8;r(0,10);-128;127;\",128,0,0,0\n"
+"\t.stabs\t\"unsigned char:t(0,11)=@s8;r(0,11);0;255;\",128,0,0,0\n"
+"\t.stabs\t\"float:t(0,12)=r(0,1);4;0;\",128,0,0,0\n"
+"\t.stabs\t\"double:t(0,13)=r(0,1);8;0;\",128,0,0,0\n"
+"\t.stabs\t\"long double:t(0,14)=r(0,1);12;0;\",128,0,0,0\n"
+"\t.stabs\t\"complex int:t(0,15)=s8real:(0,1),0,32;imag:(0,1),32,32;;\",128,0,0,0\n"
+"\t.stabs\t\"complex float:t(0,16)=R3;8;0;\",128,0,0,0\n"
+"\t.stabs\t\"complex double:t(0,17)=R4;16;0;\",128,0,0,0\n"
+"\t.stabs\t\"complex long double:t(0,18)=R5;24;0;\",128,0,0,0\n"
+"\t.stabs\t\"void:t(0,19)=(0,19)\",128,0,0,0\n"
+"\t.stabs\t\"__builtin_va_list:t(0,20)=*(0,2)\",128,0,0,0\n"
+"\t.stabs\t\"_Bool:t(0,21)=@s8;-16\",128,0,0,0\n"
+"\t.stabs\t\"user_apps.c\",130,0,0,0\n"
+"\t.stabs\t\"410kern/lib/inc/exec2obj.h\",130,0,0,0\n"
+"\t.stabs\t\"exec2obj_userapp_TOC_entry:t(2,1)=(2,2)=s264execname:(2,3)=ar(2,4)=r(2,4);0000000000000;0037777777777;;0;255;(2,5)=k(0,2),0,2048;execbytes:(2,6)=*(2,5),2048,32;execlen:(0,1),2080,32;;\",128,0,21,0\n"
+"\t.stabn\t162,0,0,0\n"
+#endif
+"\t.section\t.rodata\n"
+ ;
+
+void emit_file_header(FILE *s, const char *file, int execsize)
+{
+ fprintf(s,".globl %s_exec2obj_userapp_code_ptr\n", file);
+ fprintf(s,"\t.align 32\n");
+ fprintf(s,"\t.type\t%s_exec2obj_userapp_code_ptr, @object\n", file);
+ fprintf(s,"\t.size\t%s_exec2obj_userapp_code_ptr, %d\n", file, execsize);
+ fprintf(s,"%s_exec2obj_userapp_code_ptr:\n", file);
+}
+
+int emit_file_bytes(FILE *out, FILE *in, int bytes)
+{
+ char line[1];
+ static const size_t sz = sizeof(line) / sizeof(line[0]);
+ while (1) {
+ size_t rval = fread(line, sizeof(line[0]), sz, in);
+ if (rval <= 0)
+ break;
+ bytes -= rval;
+ fprintf(out, "\t.byte\t%d", line[0]);
+ char *it = line + 1;
+ char *end = line + rval;
+ while (it != end) {
+ fprintf(out, ",%d", *it++);
+ }
+ fprintf(out, "\n");
+ }
+ return bytes;
+}
+
+void emit_dir_header(FILE *out, int nrfiles)
+{
+ fprintf(out, ".globl exec2obj_userapp_count\n"
+ "\t.align 4\n"
+ "\t.type\texec2obj_userapp_count, @object\n"
+ "\t.size\texec2obj_userapp_count, 4\n"
+ "exec2obj_userapp_count:\n");
+ fprintf(out, "\t.long\t%d\n", nrfiles);
+ fprintf(out, ".globl exec2obj_userapp_TOC\n"
+ "\t.align 32\n"
+ "\t.type\texec2obj_userapp_TOC, @object\n");
+ fprintf(out, "\t.size\texec2obj_userapp_TOC, %d\n", sizeof(exec2obj_userapp_TOC));
+ fprintf(out, "exec2obj_userapp_TOC:\n");
+}
+
+void emit_dir_entry(FILE *out, const char *name, int size)
+{
+ /* This is an awful hack, since we want the directory listing file
+ * named something that it can't be named on the host file system
+ * and can't appear in a symbol name. */
+ const char *listed_name =
+ (strcmp(name, "__DIR_LISTING__") == 0) ? "." : name;
+
+ fprintf(out, "\t.string\t\"%s\"\n", listed_name);
+ fprintf(out, "\t.zero\t%d\n", sizeof(exec2obj_userapp_TOC[0].execname) - strlen(listed_name) - 1);
+ fprintf(out, "\t.long\t%s_exec2obj_userapp_code_ptr\n", name);
+ fprintf(out, "\t.long\t%d\n", size);
+}
+
+
+void emit_dir_footer(FILE *out, int nrfiles)
+{
+ fprintf(out, "\t.zero\t%d\n",
+ sizeof(exec2obj_userapp_TOC) - nrfiles * sizeof(exec2obj_userapp_TOC[0]));
+ fprintf(out,
+#if STABS
+ "\t.stabs\t\"exec2obj_userapp_count:G(1,1)=k(0,1)\",32,0,8,0\n"
+ "\t.stabs\t\"exec2obj_userapp_TOC:G(1,2)=ar(2,4);0;127;(1,3)=k(2,1)\",32,0,9,0\n"
+ "\t.stabs\t\"idle_exec2obj_userapp_code_ptr:G(1,4)=ar(2,4);0;9574;(2,5)\",32,0,2,0\n"
+ "\t.stabs\t\"shell_exec2obj_userapp_code_ptr:G(1,5)=ar(2,4);0;39418;(2,5)\",32,0,4,0\n"
+ "\t.stabs\t\"init_exec2obj_userapp_code_ptr:G(1,6)=ar(2,4);0;21722;(2,5)\",32,0,6,0\n"
+#endif
+ "\t.text\n"
+#if STABS
+ "\t.stabs \"\",100,0,0,.Letext\n"
+#endif
+ ".Letext:\n"
+#if STABS
+ "\t.section\t.note.GNU-stack,\"\",@progbits\n"
+ "\t.ident\t\"GCC: (GNU) 3.3.5 (Debian 1:3.3.5-13)\"\n"
+#endif
+ );
+}
+
+#define MAX_FNAME 128
+
+int main(int argc, char** argv) {
+ FILE *in;
+ int execsize = 0;
+ int file_iter = 1;
+ int execsizes[MAX_NUM_APP_ENTRIES];
+
+ char fname_buf[MAX_FNAME];
+
+ /* If there are no executables specified it's an error. */
+ if (argc < 2) {
+ print_usage();
+ return -1;
+ }
+
+ if (argc > MAX_NUM_APP_ENTRIES + 1) {
+ fprintf(stderr, "Too many executables: The maximum is %d\n", MAX_NUM_APP_ENTRIES);
+ }
+
+ fwrite(header, sizeof(header[0]), sizeof(header) / sizeof(header[0]) - 1, stdout);
+
+ while (file_iter < argc) {
+
+ strncpy(fname_buf, argv[file_iter], MAX_FNAME);
+ strncat(fname_buf, ".strip", MAX_FNAME - strlen(fname_buf));
+
+ in = fopen(fname_buf,"r");
+ if (!in) {
+ fprintf(stderr, "Could not open %s for reading; falling back.\n",fname_buf);
+
+ /* Open the executable. */
+ in = fopen(argv[file_iter],"r");
+ if (!in) {
+ fprintf(stderr, "Could not open %s for reading.\n",argv[file_iter]);
+ printf("\n\n.abort\n\n");
+ return -1;
+ }
+ }
+
+ /* Find size of executable. */
+ fseek(in,0,SEEK_END);
+ execsize = ftell(in);
+ fseek(in,0,SEEK_SET);
+
+ execsizes[file_iter] = execsize;
+
+
+ /* Output the header of the file. */
+
+ emit_file_header(stdout, argv[file_iter], execsize);
+ emit_file_bytes(stdout, in, execsize);
+
+ fclose(in);
+
+ /* Move on to the next file. */
+ file_iter++;
+ }
+
+ emit_dir_header(stdout, argc-1);
+
+ /* Output the table of contents. */
+ file_iter = 1;
+
+ /* Output all other entries in TOC. */
+ while(file_iter < argc) {
+ emit_dir_entry(stdout, argv[file_iter], execsizes[file_iter]);
+ file_iter++;
+ }
+ emit_dir_footer(stdout, argc-1);
+ return 0;
+}
diff --git a/410user/inc/410_tests.h b/410user/inc/410_tests.h
new file mode 100644
index 0000000..01d0e95
--- /dev/null
+++ b/410user/inc/410_tests.h
@@ -0,0 +1,77 @@
+/* Test program for 15-410 project 3 Fall 2003
+ * Tadashi Okoshi (slash)
+ */
+
+#ifndef _410_TESTS_H_
+#define _410_TESTS_H_
+
+#define TEST_START_CMPLT " START__TYPE_COMPLETE"
+#define TEST_START_ABORT " START__TYPE_ABORT"
+#define TEST_START_4EVER " START__TYPE_FOREVER"
+ /** An obsoleted progress detection mechanism. */
+#define TEST_START_4EVER_PROGRESS " START__TYPE_FOREVER_PROGRESS"
+
+#define TEST_END_SUCCESS " END__SUCCESS"
+#define TEST_END_FAIL " END__FAIL"
+
+/*Don't change this for now. (slash)*/
+#define TEST_PFX "(^_^)_"
+
+#include <simics.h> /* lprintf() */
+
+#ifndef ASSEMBLER
+
+#include <report.h> /* report_start(), etc. */
+
+/* macros added by mtomczak */
+/* macro assumptions:
+ 1) static char test_name[] is defined (using DEF_TEST_NAME macro)
+ 2) In each function, REPORT_LOCAL_INIT called before REPORT_ON_ERR
+*/
+
+#define DEF_TEST_NAME(x) const char *test_name = x
+
+#define REPORT_START_CMPLT report_start(START_CMPLT)
+#define REPORT_START_ABORT report_start(START_ABORT)
+#define REPORT_START_4EVER report_start(START_4EVER)
+
+#define REPORT_END_SUCCESS report_end(END_SUCCESS)
+#define REPORT_END_FAIL report_end(END_FAIL)
+
+#define REPORT_LOCAL_INIT
+#define REPORT_MISC(x) report_misc(x)
+#define REPORT_ERR(x,code) report_err(x, code)
+#define REPORT_FAIL_ERR(x,code) report_fatal(x, code)
+#define REPORT_ON_ERR(exp) report_on_err(#exp, __LINE__, exp)
+#define REPORT_FAILOUT_ON_ERR(exp) fatal_on_err(#exp, __LINE__, exp)
+
+/**************************************************/
+/*memo*/
+/*
+
+//At the beginning of the test code.
+lprintf("%s%s%s",TEST_PFX,test_name,TEST_START_CMPLT);
+ or
+lprintf("%s%s%s",TEST_PFX,test_name,TEST_START_ABORT);
+ or
+lprintf("%s%s%s",TEST_PFX,test_name,TEST_START_4EVER);
+
+//In the test body...
+....
+lprintf("%s%s%s",TEST_PFX,test_name,"foo mesg.");
+lprintf("%s%s%s",TEST_PFX,test_name,"bar mesg.");
+....
+
+//At the end of the test (only START_CMPLT case)
+lprintf("%s%s%s",TEST_PFX,test_name,TEST_END_SUCCESS);
+ or
+lprintf("%s%s%s",TEST_PFX,test_name,TEST_END_FAIL);
+
+*/
+
+#define TEST_PROG_ENGAGE(i) sim_fr_prog(i)
+#define TEST_PROG_PROGRESS sim_fr_here()
+
+#endif /* !ASSEMBLER */
+
+#endif /* _410_TESTS_H_ */
diff --git a/410user/inc/asm_style.h b/410user/inc/asm_style.h
new file mode 100644
index 0000000..6af13da
--- /dev/null
+++ b/410user/inc/asm_style.h
@@ -0,0 +1,126 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+#ifndef _ASM_STYLE_H_
+#define _ASM_STYLE_H_
+
+/* 15-410 */
+#ifndef HAVE_P2ALIGN
+#define HAVE_P2ALIGN
+#endif
+#ifndef __ELF__
+#define __ELF__
+#endif
+/* 15-410 */
+
+/* This is a more reliable delay than a few short jmps. */
+#define IODELAY pushl %eax; inb $0x80,%al; inb $0x80,%al; popl %eax
+
+#define S_ARG0 4(%esp)
+#define S_ARG1 8(%esp)
+#define S_ARG2 12(%esp)
+#define S_ARG3 16(%esp)
+
+#define FRAME pushl %ebp; movl %esp, %ebp
+#define EMARF leave
+
+#define B_ARG0 8(%ebp)
+#define B_ARG1 12(%ebp)
+#define B_ARG2 16(%ebp)
+#define B_ARG3 20(%ebp)
+
+#ifdef i486
+#define TEXT_ALIGN 4
+#else
+#define TEXT_ALIGN 2
+#endif
+#define DATA_ALIGN 2
+#define ALIGN TEXT_ALIGN
+
+/*
+ * The .align directive has different meaning on the x86 when using ELF
+ * than when using a.out.
+ * Newer GNU as remedies this problem by providing .p2align and .balign.
+ */
+#if defined(HAVE_P2ALIGN)
+# define P2ALIGN(p2) .p2align p2
+#elif defined(__ELF__)
+# define P2ALIGN(p2) .align (1<<(p2))
+#else
+# define P2ALIGN(p2) .align p2
+#endif
+
+#define LCL(x) x
+
+#define LB(x,n) n
+#ifndef __ELF__
+#define EXT(x) _ ## x
+#define LEXT(x) _ ## x ## :
+#define SEXT(x) "_"#x
+#else
+#define EXT(x) x
+#define LEXT(x) x ## :
+#define SEXT(x) #x
+#endif
+#define GLEXT(x) .globl EXT(x); LEXT(x)
+#define LCLL(x) x ## :
+#define gLB(n) n ## :
+#define LBb(x,n) n ## b
+#define LBf(x,n) n ## f
+
+
+/* Symbol types */
+#ifdef __ELF__
+#define FUNCSYM(x) .type x,@function
+#else
+#define FUNCSYM(x) /* nothing */
+#endif
+
+
+#ifdef GPROF
+
+#define MCOUNT .data; gLB(9) .long 0; .text; lea LBb(x, 9),%edx; call mcount
+#define ENTRY(x) .globl EXT(x); P2ALIGN(TEXT_ALIGN); LEXT(x) ; \
+ pushl %ebp; movl %esp, %ebp; MCOUNT; popl %ebp;
+#define ENTRY2(x,y) .globl EXT(x); .globl EXT(y); \
+ P2ALIGN(TEXT_ALIGN); LEXT(x) LEXT(y)
+#define ASENTRY(x) .globl x; P2ALIGN(TEXT_ALIGN); gLB(x) ; \
+ pushl %ebp; movl %esp, %ebp; MCOUNT; popl %ebp;
+
+#else /* ndef GPROF */
+
+#define MCOUNT
+#define ENTRY(x) FUNCSYM(x); .globl EXT(x); P2ALIGN(TEXT_ALIGN); LEXT(x)
+#define ENTRY2(x,y) .globl EXT(x); .globl EXT(y); \
+ P2ALIGN(TEXT_ALIGN); LEXT(x) LEXT(y)
+#define ASENTRY(x) .globl x; P2ALIGN(TEXT_ALIGN); gLB(x)
+
+#endif /* ndef GPROF */
+
+
+#define Entry(x) P2ALIGN(TEXT_ALIGN); GLEXT(x)
+#define DATA(x) P2ALIGN(DATA_ALIGN); GLEXT(x)
+
+#endif /* _ASM_STYLE_H_ */
diff --git a/410user/inc/assert.h b/410user/inc/assert.h
new file mode 100644
index 0000000..0d989a8
--- /dev/null
+++ b/410user/inc/assert.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1995 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _ASSERT_H_
+#define _ASSERT_H_
+
+extern void panic(const char *format, ...);
+
+#ifndef NDEBUG
+#define assert(expression) do { \
+ if(!(expression)) { \
+ panic("%s:%u: failed assertion `%s'", __FILE__, __LINE__, #expression);\
+ } \
+} while(0)
+#else
+#define assert(expression) ((void)0)
+#endif
+
+/* Extended for 15-410 at Carnegie Mellon.
+ *
+ * The following conditions are checked even if NDEBUG is defined:
+ * affirm(3 > 0);
+ * affirm_msg(3 > 0, "arithmetic broken around %d and %d", 3, 0);
+ * reject(0 > 3);
+ * reject_msg(0 > 3, "arithmetic broken around %d and %d", 0, 3);
+ */
+
+#define affirm(expression) do { \
+ if(!(expression)) { \
+ panic("%s:%u: failed affirmation `%s'", \
+ __FILE__, __LINE__, #expression); \
+ } \
+} while(0)
+
+#define reject(expression) do { \
+ if(expression) { \
+ panic("%s:%u: rejecting result `%s'", __FILE__, __LINE__, #expression);\
+ } \
+} while(0)
+
+#define affirm_msg(expression, ...) do { \
+ if(!(expression)) { \
+ panic(__VA_ARGS__); \
+ } \
+} while(0)
+
+#define reject_msg(expression, ...) \
+ affirm_msg(!(expression), __VA_ARGS__)
+
+#endif /* _ASSERT_H_ */
diff --git a/410user/inc/cond.h b/410user/inc/cond.h
new file mode 100644
index 0000000..aa12609
--- /dev/null
+++ b/410user/inc/cond.h
@@ -0,0 +1,18 @@
+/** @file cond.h
+ * @brief This file defines the interface for condition variables.
+ */
+
+#ifndef COND_H
+#define COND_H
+
+#include <mutex.h>
+#include <cond_type.h>
+
+/* condition variable functions */
+int cond_init( cond_t *cv );
+void cond_destroy( cond_t *cv );
+void cond_wait( cond_t *cv, mutex_t *mp );
+void cond_signal( cond_t *cv );
+void cond_broadcast( cond_t *cv );
+
+#endif /* COND_H */
diff --git a/410user/inc/malloc.h b/410user/inc/malloc.h
new file mode 100644
index 0000000..88827f6
--- /dev/null
+++ b/410user/inc/malloc.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+#include <types.h>
+
+#ifndef _MALLOC_WRAPPERS_H_
+#define _MALLOC_WRAPPERS_H_
+
+void *malloc(size_t size);
+void *calloc(size_t nelt, size_t eltsize);
+void *realloc(void *buf, size_t new_size);
+void free(void *buf);
+
+void *_malloc(size_t size);
+void *_calloc(size_t nelt, size_t eltsize);
+void *_realloc(void *buf, size_t new_size);
+void _free(void *buf);
+
+#endif /* _MALLOC_WRAPPERS_H_ */
diff --git a/410user/inc/mutex.h b/410user/inc/mutex.h
new file mode 100644
index 0000000..36ec0e1
--- /dev/null
+++ b/410user/inc/mutex.h
@@ -0,0 +1,15 @@
+/** @file mutex.h
+ * @brief This file defines the interface for mutexes.
+ */
+
+#ifndef MUTEX_H
+#define MUTEX_H
+
+#include <mutex_type.h>
+
+int mutex_init( mutex_t *mp );
+void mutex_destroy( mutex_t *mp );
+void mutex_lock( mutex_t *mp );
+void mutex_unlock( mutex_t *mp );
+
+#endif /* MUTEX_H */
diff --git a/410user/inc/rand.h b/410user/inc/rand.h
new file mode 100644
index 0000000..6c23819
--- /dev/null
+++ b/410user/inc/rand.h
@@ -0,0 +1,35 @@
+/* A C-program for MT19937: Integer version */
+/* genrand() generates one pseudorandom unsigned integer (32bit) */
+/* which is uniformly distributed among 0 to 2^32-1 for each */
+/* call. sgenrand(seed) set initial values to the working area */
+/* of 624 words. Before genrand(), sgenrand(seed) must be */
+/* called once. (seed is any 32-bit integer except for 0). */
+/* Coded by Takuji Nishimura, considering the suggestions by */
+/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */
+
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later */
+/* version. */
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
+/* See the GNU Library General Public License for more details. */
+/* You should have received a copy of the GNU Library General */
+/* Public License along with this library; if not, write to the */
+/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
+/* 02111-1307 USA */
+
+/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
+/* Any feedback is very welcome. For any question, comments, */
+/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */
+/* matumoto@math.keio.ac.jp */
+
+#ifndef _RAND_H
+#define _RAND_H
+
+void sgenrand( unsigned long );
+unsigned long genrand( void );
+
+#endif /* _RAND_H */
diff --git a/410user/inc/rwlock.h b/410user/inc/rwlock.h
new file mode 100644
index 0000000..ad793f8
--- /dev/null
+++ b/410user/inc/rwlock.h
@@ -0,0 +1,20 @@
+/** @file rwlock.h
+ * @brief This file defines the interface to readers/writers locks
+ */
+
+#ifndef RWLOCK_H
+#define RWLOCK_H
+
+#define RWLOCK_READ 0
+#define RWLOCK_WRITE 1
+
+#include <rwlock_type.h>
+
+/* readers/writers lock functions */
+int rwlock_init( rwlock_t *rwlock );
+void rwlock_lock( rwlock_t *rwlock, int type );
+void rwlock_unlock( rwlock_t *rwlock );
+void rwlock_destroy( rwlock_t *rwlock );
+void rwlock_downgrade( rwlock_t *rwlock);
+
+#endif /* RW_H */
diff --git a/410user/inc/sem.h b/410user/inc/sem.h
new file mode 100644
index 0000000..8509042
--- /dev/null
+++ b/410user/inc/sem.h
@@ -0,0 +1,16 @@
+/** @file sem.h
+ * @brief This file defines the interface to semaphores
+ */
+
+#ifndef SEM_H
+#define SEM_H
+
+#include <sem_type.h>
+
+/* semaphore functions */
+int sem_init( sem_t *sem, int count );
+void sem_wait( sem_t *sem );
+void sem_signal( sem_t *sem );
+void sem_destroy( sem_t *sem );
+
+#endif /* SEM_H */
diff --git a/410user/inc/stdarg.h b/410user/inc/stdarg.h
new file mode 100644
index 0000000..ba9add0
--- /dev/null
+++ b/410user/inc/stdarg.h
@@ -0,0 +1,18 @@
+#ifndef _STDARG_H_
+#define _STDARG_H_
+
+/* This is awful, but really these are compiler intrinsics, so we use the
+ * GNU compiler intrinsics.
+ */
+
+#ifdef __GNUC__
+typedef __builtin_va_list va_list;
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#define va_copy(d,s) __builtin_va_copy(d,s)
+#else
+#error "Don't know how to use varargs not on GNUC, sorry."
+#endif
+
+#endif
diff --git a/410user/inc/stdbool.h b/410user/inc/stdbool.h
new file mode 100644
index 0000000..5060f36
--- /dev/null
+++ b/410user/inc/stdbool.h
@@ -0,0 +1,15 @@
+/** @file stdbool.h
+ * @author John Gallagher (gallaghe)
+ */
+
+#ifndef _STDBOOL_H_
+#define _STDBOOL_H_
+
+#define bool _Bool
+
+#define false 0
+#define true 1
+
+#define __bool_true_false_are_defined 1
+
+#endif /* _STDBOOL_H_ */
diff --git a/410user/inc/stddef.h b/410user/inc/stddef.h
new file mode 100644
index 0000000..b321b53
--- /dev/null
+++ b/410user/inc/stddef.h
@@ -0,0 +1,12 @@
+#ifndef _STDDEF_H_
+#define _STDDEF_H_
+
+#include <types.h> /* for size_t, ptrdiff_t */
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define offsetof(stype,field) ((size_t)(&((stype*)NULL)->field))
+
+#endif /* _STDDEF_H_ */
diff --git a/410user/inc/stdint.h b/410user/inc/stdint.h
new file mode 100644
index 0000000..9bdf21c
--- /dev/null
+++ b/410user/inc/stdint.h
@@ -0,0 +1,114 @@
+/** @file lib/stdint.h
+ *
+ * @brief Standard integer type definitions
+ *
+ * @bug The standard integer state of our library is a little questionable.
+ * I think types.h has become a dumping ground for things that don't fit well,
+ * and some of that should move here/be deleted.
+ * It's missing a few things that it probably should have (wchar, ptrdiff
+ * sizing), but I think it should be fine until students actually use those
+ * features.
+ *
+ * @author matthewj S2008
+ @author Matt Bryant (mbryant) S'16
+ */
+
+#ifndef LIB_STDINT_H
+#define LIB_STDINT_H
+
+#ifndef ASSEMBLER
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed long int32_t;
+typedef signed long long int64_t;
+
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+#endif /* !ASSEMBLER */
+
+#define UINT8_C(x) (x)
+#define UINT16_C(x) (x)
+#define UINT32_C(x) (x ## U)
+#define UINT64_C(x) (x ## ULL)
+
+#define INT8_C(x) (x)
+#define INT16_C(x) (x)
+#define INT32_C(x) (x)
+#define INT64_C(x) (x ## LL)
+
+#define INTMAX_C(x) (x ## LL)
+#define UINTMAX_C(x) (x ## ULL)
+
+#define INT8_MIN (-128)
+#define INT8_MAX (127)
+#define INT16_MIN (-32768)
+#define INT16_MAX (32767)
+#define INT32_MIN (0x80000000)
+#define INT32_MAX (0x7FFFFFFF)
+#define INT64_MIN (0x8000000000000000LL)
+#define INT64_MAX (0x7FFFFFFFFFFFFFFFLL)
+
+#define UINT8_MAX (255)
+#define UINT16_MAX (65535)
+#define UINT32_MAX (0xFFFFFFFF)
+#define UINT64_MAX (0xFFFFFFFFFFFFFFFFULL)
+
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+#endif /* !LIB_STDINT_H */
diff --git a/410user/inc/thread.h b/410user/inc/thread.h
new file mode 100644
index 0000000..cd8358f
--- /dev/null
+++ b/410user/inc/thread.h
@@ -0,0 +1,26 @@
+/** @file thread.h
+ * @brief This file defines thread-management interface.
+ *
+ * It should NOT contain any of the thread library internals.
+ * Therefore, you may NOT modify this file.
+ *
+ * However, you MAY modify user/libthread/thr_internals.h.
+ *
+ */
+
+
+
+#ifndef THREAD_H
+#define THREAD_H
+
+#include <thr_internals.h>
+
+/* thread library functions */
+int thr_init( unsigned int size );
+int thr_create( void *(*func)(void *), void *args );
+int thr_join( int tid, void **statusp );
+void thr_exit( void *status );
+int thr_getid( void );
+int thr_yield( int tid );
+
+#endif /* THREAD_H */
diff --git a/410user/inc/types.h b/410user/inc/types.h
new file mode 100644
index 0000000..eef2003
--- /dev/null
+++ b/410user/inc/types.h
@@ -0,0 +1,23 @@
+/** @file lib/types.h
+ * @brief Defines some C standard types as well as
+ * wrapper types for some of the imported FLUX library code.
+ * @author matthewj S2008
+ */
+
+#ifndef LIB_TYPES_H
+#define LIB_TYPES_H
+
+typedef unsigned int size_t;
+typedef unsigned long ptrdiff_t;
+
+/* WRAPPERS */
+
+typedef unsigned long vm_offset_t;
+typedef unsigned long vm_size_t;
+
+typedef enum {
+ FALSE = 0,
+ TRUE
+} boolean_t;
+
+#endif /* !LIB_TYPES_H */
diff --git a/410user/libRNG/mt19937int.c b/410user/libRNG/mt19937int.c
new file mode 100644
index 0000000..809bc01
--- /dev/null
+++ b/410user/libRNG/mt19937int.c
@@ -0,0 +1,97 @@
+/* A C-program for MT19937: Integer version */
+/* genrand() generates one pseudorandom unsigned integer (32bit) */
+/* which is uniformly distributed among 0 to 2^32-1 for each */
+/* call. sgenrand(seed) set initial values to the working area */
+/* of 624 words. Before genrand(), sgenrand(seed) must be */
+/* called once. (seed is any 32-bit integer except for 0). */
+/* Coded by Takuji Nishimura, considering the suggestions by */
+/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */
+
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later */
+/* version. */
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
+/* See the GNU Library General Public License for more details. */
+/* You should have received a copy of the GNU Library General */
+/* Public License along with this library; if not, write to the */
+/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
+/* 02111-1307 USA */
+
+/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
+/* Any feedback is very welcome. For any question, comments, */
+/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */
+/* matumoto@math.keio.ac.jp */
+
+/* modified for 15-410 at CMU by Zachary Anderson(zra) */
+
+/* Period parameters */
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0df /* constant vector a */
+#define UPPER_MASK 0x80000000 /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffff /* least significant r bits */
+
+/* Tempering parameters */
+#define TEMPERING_MASK_B 0x9d2c5680
+#define TEMPERING_MASK_C 0xefc60000
+#define TEMPERING_SHIFT_U(y) (y >> 11)
+#define TEMPERING_SHIFT_S(y) (y << 7)
+#define TEMPERING_SHIFT_T(y) (y << 15)
+#define TEMPERING_SHIFT_L(y) (y >> 18)
+
+static unsigned long mt[N]; /* the array for the state vector */
+static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
+
+/* initializing the array with a NONZERO seed */
+void
+sgenrand(seed)
+unsigned long seed;
+{
+ /* setting initial seeds to mt[N] using */
+ /* the generator Line 25 of Table 1 in */
+ /* [KNUTH 1981, The Art of Computer Programming */
+ /* Vol. 2 (2nd Ed.), pp102] */
+ mt[0]= seed & 0xffffffff;
+ for (mti=1; mti<N; mti++)
+ mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
+}
+
+unsigned long
+genrand()
+{
+ unsigned long y;
+ static unsigned long mag01[2]={0x0, MATRIX_A};
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ if (mti >= N) { /* generate N words at one time */
+ int kk;
+
+ if (mti == N+1) /* if sgenrand() has not been called, */
+ sgenrand(4357); /* a default initial seed is used */
+
+ for (kk=0;kk<N-M;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
+ }
+ for (;kk<N-1;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
+ }
+ y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+ mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
+
+ mti = 0;
+ }
+
+ y = mt[mti++];
+ y ^= TEMPERING_SHIFT_U(y);
+ y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
+ y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
+ y ^= TEMPERING_SHIFT_L(y);
+
+ return y;
+}
diff --git a/410user/libRNG/user.mk b/410user/libRNG/user.mk
new file mode 100644
index 0000000..29b2bb7
--- /dev/null
+++ b/410user/libRNG/user.mk
@@ -0,0 +1,6 @@
+410ULIB_RNG_OBJS = $(410UDIR)/libRNG/mt19937int.o
+
+ALL_410UOBJS += $(410ULIB_RNG_OBJS)
+410UCLEANS += $(410UDIR)/libRNG.a
+
+$(410UDIR)/libRNG.a: $(410ULIB_RNG_OBJS)
diff --git a/410user/libmalloc/malloc.c b/410user/libmalloc/malloc.c
new file mode 100644
index 0000000..90bcf99
--- /dev/null
+++ b/410user/libmalloc/malloc.c
@@ -0,0 +1,639 @@
+/*
+ ******************************************************************************
+ * mm-baseline.c *
+ * 64-bit struct-based implicit free list memory allocator *
+ * 15-213: Introduction to Computer Systems *
+ * *
+ * ************************************************************************ *
+ * DOCUMENTATION *
+ * *
+ * ** STRUCTURE. ** *
+ * *
+ * Both allocated and free blocks share the same header structure. *
+ * HEADER: 8-byte, aligned to 8th byte of an 16-byte aligned heap, where *
+ * - The lowest order bit is 1 when the block is allocated, and *
+ * 0 otherwise. *
+ * - The whole 8-byte value with the least significant bit set to 0 *
+ * represents the size of the block as a size_t *
+ * The size of a block includes the header and footer. *
+ * FOOTER: 8-byte, aligned to 0th byte of an 16-byte aligned heap. It *
+ * contains the exact copy of the block's header. *
+ * The minimum blocksize is 32 bytes. *
+ * *
+ * Allocated blocks contain the following: *
+ * HEADER, as defined above. *
+ * PAYLOAD: Memory allocated for program to store information. *
+ * FOOTER, as defined above. *
+ * The size of an allocated block is exactly PAYLOAD + HEADER + FOOTER. *
+ * *
+ * Free blocks contain the following: *
+ * HEADER, as defined above. *
+ * FOOTER, as defined above. *
+ * The size of an unallocated block is at least 32 bytes. *
+ * *
+ * Block Visualization. *
+ * block block+8 block+size-8 block+size *
+ * Allocated blocks: | HEADER | ... PAYLOAD ... | FOOTER | *
+ * *
+ * block block+8 block+size-8 block+size *
+ * Unallocated blocks: | HEADER | ... (empty) ... | FOOTER | *
+ * *
+ * ************************************************************************ *
+ * ** INITIALIZATION. ** *
+ * *
+ * The following visualization reflects the beginning of the heap. *
+ * start start+8 start+16 *
+ * INIT: | PROLOGUE_FOOTER | EPILOGUE_HEADER | *
+ * PROLOGUE_FOOTER: 8-byte footer, as defined above, that simulates the *
+ * end of an allocated block. Also serves as padding. *
+ * EPILOGUE_HEADER: 8-byte block indicating the end of the heap. *
+ * It simulates the beginning of an allocated block *
+ * The epilogue header is moved when the heap is extended. *
+ * *
+ * ************************************************************************ *
+ * ** BLOCK ALLOCATION. ** *
+ * *
+ * Upon memory request of size S, a block of size S + dsize, rounded up to *
+ * 16 bytes, is allocated on the heap, where dsize is 2*8 = 16. *
+ * Selecting the block for allocation is performed by finding the first *
+ * block that can fit the content based on a first-fit or next-fit search *
+ * policy. *
+ * The search starts from the beginning of the heap pointed by heap_listp. *
+ * It sequentially goes through each block in the implicit free list, *
+ * the end of the heap, until either *
+ * - A sufficiently-large unallocated block is found, or *
+ * - The end of the implicit free list is reached, which occurs *
+ * when no sufficiently-large unallocated block is available. *
+ * In case that a sufficiently-large unallocated block is found, then *
+ * that block will be used for allocation. Otherwise--that is, when no *
+ * sufficiently-large unallocated block is found--then more unallocated *
+ * memory of size chunksize or requested size, whichever is larger, is *
+ * requested through mem_sbrk, and the search is redone. *
+ * *
+ * ************************************************************************ *
+ * ** ADVICE FOR STUDENTS. ** *
+ * Step 0: Please read the writeup! *
+ * Write your heap checker. Write your heap checker. Write. Heap. checker. *
+ * Good luck, and have fun! *
+ * *
+ ******************************************************************************
+ */
+
+/* Do not change the following! */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#undef NDEBUG // the assert()s in this particular implementation are all O(1) and vital
+#include <assert.h>
+
+#include "memlib.h"
+
+#define dbg_requires(...) assert(__VA_ARGS__)
+#define dbg_assert(...) assert(__VA_ARGS__)
+#define dbg_ensures(...) assert(__VA_ARGS__)
+
+/* Basic constants */
+typedef uint64_t word_t;
+static const size_t wsize = sizeof(word_t); // word and header size (bytes)
+static const size_t dsize = 2*sizeof(word_t); // double word size (bytes)
+static const size_t min_block_size = 4*sizeof(word_t); // Minimum block size
+static const size_t chunksize = (1 << 12); // requires (chunksize % 16 == 0)
+
+static const word_t alloc_mask = 0x1;
+static const word_t size_mask = ~(word_t)0xF;
+
+typedef struct block
+{
+ /* Header contains size + allocation flag */
+ word_t header;
+ /*
+ * We don't know how big the payload will be. Declaring it as an
+ * array of size 0 allows computing its starting address using
+ * pointer notation.
+ */
+ char payload[0];
+ /*
+ * We can't declare the footer as part of the struct, since its starting
+ * position is unknown
+ */
+} block_t;
+
+
+/* Global variables */
+/* Pointer to first block */
+static block_t *heap_listp = NULL;
+
+/* Function prototypes for internal helper routines */
+static block_t *extend_heap(size_t size);
+static void place(block_t *block, size_t asize);
+static block_t *find_fit(size_t asize);
+static block_t *coalesce(block_t *block);
+
+static size_t max(size_t x, size_t y);
+static size_t round_up(size_t size, size_t n);
+static word_t pack(size_t size, bool alloc);
+
+static size_t extract_size(word_t header);
+static size_t get_size(block_t *block);
+static size_t get_payload_size(block_t *block);
+
+static bool extract_alloc(word_t header);
+static bool get_alloc(block_t *block);
+
+static void write_header(block_t *block, size_t size, bool alloc);
+static void write_footer(block_t *block, size_t size, bool alloc);
+
+static block_t *payload_to_header(void *bp);
+static void *header_to_payload(block_t *block);
+
+static block_t *find_next(block_t *block);
+static word_t *find_prev_footer(block_t *block);
+static block_t *find_prev(block_t *block);
+
+bool mm_checkheap(int lineno);
+
+/*
+ * mm_init: initializes the heap; it is run once when heap_start == NULL.
+ * prior to any extend_heap operation, this is the heap:
+ * start start+8 start+16
+ * INIT: | PROLOGUE_FOOTER | EPILOGUE_HEADER |
+ * heap_listp ends up pointing to the epilogue header.
+ */
+bool mm_init(void)
+{
+ mem_init(0xffffffff);
+
+ // Create the initial empty heap
+ word_t *start = (word_t *)(mem_sbrk(2*wsize));
+
+ if (start == NULL)
+ {
+ return false;
+ }
+
+ start[0] = pack(0, true); // Prologue footer
+ start[1] = pack(0, true); // Epilogue header
+ // Heap starts with first block header (epilogue)
+ heap_listp = (block_t *) &(start[1]);
+
+ // Extend the empty heap with a free block of chunksize bytes
+ if (extend_heap(chunksize) == NULL)
+ {
+ return false;
+ }
+ return true;
+}
+
+/*
+ * malloc: allocates a block with size at least (size + dsize), rounded up to
+ * the nearest 16 bytes, with a minimum of 2*dsize. Seeks a
+ * sufficiently-large unallocated block on the heap to be allocated.
+ * If no such block is found, extends heap by the maximum between
+ * chunksize and (size + dsize) rounded up to the nearest 16 bytes,
+ * and then attempts to allocate all, or a part of, that memory.
+ * Returns NULL on failure, otherwise returns a pointer to such block.
+ * The allocated block will not be used for further allocations until
+ * freed.
+ */
+void *_malloc(size_t size)
+{
+ dbg_requires(mm_checkheap(__LINE__));
+
+ size_t asize; // Adjusted block size
+ size_t extendsize; // Amount to extend heap if no fit is found
+ block_t *block;
+ void *bp = NULL;
+
+ if (heap_listp == NULL) // Initialize heap if it isn't initialized
+ {
+ mm_init();
+ }
+
+ if (size == 0) // Ignore spurious request
+ {
+ dbg_ensures(mm_checkheap(__LINE__));
+ return bp;
+ }
+
+ // Adjust block size to include overhead and to meet alignment requirements
+ asize = round_up(size, dsize) + dsize;
+
+ // Search the free list for a fit
+ block = find_fit(asize);
+
+ // If no fit is found, request more memory, and then and place the block
+ if (block == NULL)
+ {
+ extendsize = max(asize, chunksize);
+ block = extend_heap(extendsize);
+ if (block == NULL) // extend_heap returns an error
+ {
+ return bp;
+ }
+
+ }
+
+ place(block, asize);
+ bp = header_to_payload(block);
+
+ dbg_ensures(mm_checkheap(__LINE__));
+ return bp;
+}
+
+/*
+ * free: Frees the block such that it is no longer allocated while still
+ * maintaining its size. Block will be available for use on malloc.
+ */
+void _free(void *bp)
+{
+ if (bp == NULL)
+ {
+ return;
+ }
+
+ block_t *block = payload_to_header(bp);
+ size_t size = get_size(block);
+
+ write_header(block, size, false);
+ write_footer(block, size, false);
+
+ coalesce(block);
+
+}
+
+/*
+ * realloc: returns a pointer to an allocated region of at least size bytes:
+ * if ptrv is NULL, then call malloc(size);
+ * if size == 0, then call free(ptr) and returns NULL;
+ * else allocates new region of memory, copies old data to new memory,
+ * and then free old block. Returns old block if realloc fails or
+ * returns new pointer on success.
+ */
+void *_realloc(void *ptr, size_t size)
+{
+ block_t *block = payload_to_header(ptr);
+ size_t copysize;
+ void *newptr;
+
+ // If size == 0, then free block and return NULL
+ if (size == 0)
+ {
+ _free(ptr);
+ return NULL;
+ }
+
+ // If ptr is NULL, then equivalent to malloc
+ if (ptr == NULL)
+ {
+ return _malloc(size);
+ }
+
+ // Otherwise, proceed with reallocation
+ newptr = _malloc(size);
+ // If malloc fails, the original block is left untouched
+ if (!newptr)
+ {
+ return NULL;
+ }
+
+ // Copy the old data
+ copysize = get_payload_size(block); // gets size of old payload
+ if(size < copysize)
+ {
+ copysize = size;
+ }
+ memcpy(newptr, ptr, copysize);
+
+ // Free the old block
+ _free(ptr);
+
+ return newptr;
+}
+
+/*
+ * calloc: Allocates a block with size at least (elements * size + dsize)
+ * through malloc, then initializes all bits in allocated memory to 0.
+ * Returns NULL on failure.
+ */
+void *_calloc(size_t nmemb, size_t size)
+{
+ void *bp;
+ size_t asize = nmemb * size;
+
+ if (asize/nmemb != size)
+ // Multiplication overflowed
+ return NULL;
+
+ bp = _malloc(asize);
+ if (bp == NULL)
+ {
+ return NULL;
+ }
+ // Initialize all bits to 0
+ memset(bp, 0, asize);
+
+ return bp;
+}
+
+/******** The remaining content below are helper and debug routines ********/
+
+/*
+ * extend_heap: Extends the heap with the requested number of bytes, and
+ * recreates epilogue header. Returns a pointer to the result of
+ * coalescing the newly-created block with previous free block, if
+ * applicable, or NULL in failure.
+ */
+static block_t *extend_heap(size_t size)
+{
+ void *bp;
+
+ // Allocate an even number of words to maintain alignment
+ size = round_up(size, dsize);
+ if ((bp = mem_sbrk(size)) == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize free block header/footer
+ block_t *block = payload_to_header(bp);
+ write_header(block, size, false);
+ write_footer(block, size, false);
+ // Create new epilogue header
+ block_t *block_next = find_next(block);
+ write_header(block_next, 0, true);
+
+ // Coalesce in case the previous block was free
+ return coalesce(block);
+}
+
+/* Coalesce: Coalesces current block with previous and next blocks if either
+ * or both are unallocated; otherwise the block is not modified.
+ * Returns pointer to the coalesced block. After coalescing, the
+ * immediate contiguous previous and next blocks must be allocated.
+ */
+static block_t *coalesce(block_t * block)
+{
+ block_t *block_next = find_next(block);
+ block_t *block_prev = find_prev(block);
+
+ bool prev_alloc = extract_alloc(*(find_prev_footer(block)));
+ bool next_alloc = get_alloc(block_next);
+ size_t size = get_size(block);
+
+ if (prev_alloc && next_alloc) // Case 1
+ {
+ return block;
+ }
+
+ else if (prev_alloc && !next_alloc) // Case 2
+ {
+ size += get_size(block_next);
+ write_header(block, size, false);
+ write_footer(block, size, false);
+ }
+
+ else if (!prev_alloc && next_alloc) // Case 3
+ {
+ size += get_size(block_prev);
+ write_header(block_prev, size, false);
+ write_footer(block_prev, size, false);
+ block = block_prev;
+ }
+
+ else // Case 4
+ {
+ size += get_size(block_next) + get_size(block_prev);
+ write_header(block_prev, size, false);
+ write_footer(block_prev, size, false);
+
+ block = block_prev;
+ }
+ return block;
+}
+
+/*
+ * place: Places block with size of asize at the start of bp. If the remaining
+ * size is at least the minimum block size, then split the block to the
+ * the allocated block and the remaining block as free, which is then
+ * inserted into the segregated list. Requires that the block is
+ * initially unallocated.
+ */
+static void place(block_t *block, size_t asize)
+{
+ size_t csize = get_size(block);
+
+ if ((csize - asize) >= min_block_size)
+ {
+ block_t *block_next;
+ write_header(block, asize, true);
+ write_footer(block, asize, true);
+
+ block_next = find_next(block);
+ write_header(block_next, csize-asize, false);
+ write_footer(block_next, csize-asize, false);
+ }
+
+ else
+ {
+ write_header(block, csize, true);
+ write_footer(block, csize, true);
+ }
+}
+
+/*
+ * find_fit: Looks for a free block with at least asize bytes with
+ * first-fit policy. Returns NULL if none is found.
+ */
+static block_t *find_fit(size_t asize)
+{
+ block_t *block;
+
+ for (block = heap_listp; get_size(block) > 0;
+ block = find_next(block))
+ {
+
+ if (!(get_alloc(block)) && (asize <= get_size(block)))
+ {
+ return block;
+ }
+ }
+ return NULL; // no fit found
+}
+
+/*
+ * max: returns x if x > y, and y otherwise.
+ */
+static size_t max(size_t x, size_t y)
+{
+ return (x > y) ? x : y;
+}
+
+
+/*
+ * round_up: Rounds size up to next multiple of n
+ */
+static size_t round_up(size_t size, size_t n)
+{
+ return (n * ((size + (n-1)) / n));
+}
+
+/*
+ * pack: returns a header reflecting a specified size and its alloc status.
+ * If the block is allocated, the lowest bit is set to 1, and 0 otherwise.
+ */
+static word_t pack(size_t size, bool alloc)
+{
+ return alloc ? (size | 1) : size;
+}
+
+
+/*
+ * extract_size: returns the size of a given header value based on the header
+ * specification above.
+ */
+static size_t extract_size(word_t word)
+{
+ return (word & size_mask);
+}
+
+/*
+ * get_size: returns the size of a given block by clearing the lowest 4 bits
+ * (as the heap is 16-byte aligned).
+ */
+static size_t get_size(block_t *block)
+{
+ return extract_size(block->header);
+}
+
+/*
+ * get_payload_size: returns the payload size of a given block, equal to
+ * the entire block size minus the header and footer sizes.
+ */
+static size_t get_payload_size(block_t *block)
+{
+ size_t asize = get_size(block);
+ return asize - dsize;
+}
+
+/*
+ * extract_alloc: returns the allocation status of a given header value based
+ * on the header specification above.
+ */
+static bool extract_alloc(word_t word)
+{
+ return (bool)(word & alloc_mask);
+}
+
+/*
+ * get_alloc: returns true when the block is allocated based on the
+ * block header's lowest bit, and false otherwise.
+ */
+static bool get_alloc(block_t *block)
+{
+ return extract_alloc(block->header);
+}
+
+/*
+ * write_header: given a block and its size and allocation status,
+ * writes an appropriate value to the block header.
+ */
+static void write_header(block_t *block, size_t size, bool alloc)
+{
+ block->header = pack(size, alloc);
+}
+
+
+/*
+ * write_footer: given a block and its size and allocation status,
+ * writes an appropriate value to the block footer by first
+ * computing the position of the footer.
+ */
+static void write_footer(block_t *block, size_t size, bool alloc)
+{
+ word_t *footerp = (word_t *)((block->payload) + get_size(block) - dsize);
+ *footerp = pack(size, alloc);
+}
+
+
+/*
+ * find_next: returns the next consecutive block on the heap by adding the
+ * size of the block.
+ */
+static block_t *find_next(block_t *block)
+{
+ dbg_requires(block != NULL);
+ block_t *block_next = (block_t *)(((char *)block) + get_size(block));
+
+ dbg_ensures(block_next != NULL);
+ return block_next;
+}
+
+/*
+ * find_prev_footer: returns the footer of the previous block.
+ */
+static word_t *find_prev_footer(block_t *block)
+{
+ // Compute previous footer position as one word before the header
+ return (&(block->header)) - 1;
+}
+
+/*
+ * find_prev: returns the previous block position by checking the previous
+ * block's footer and calculating the start of the previous block
+ * based on its size.
+ */
+static block_t *find_prev(block_t *block)
+{
+ word_t *footerp = find_prev_footer(block);
+ size_t size = extract_size(*footerp);
+ return (block_t *)((char *)block - size);
+}
+
+/*
+ * payload_to_header: given a payload pointer, returns a pointer to the
+ * corresponding block.
+ */
+static block_t *payload_to_header(void *bp)
+{
+ return (block_t *)(((char *)bp) - offsetof(block_t, payload));
+}
+
+/*
+ * header_to_payload: given a block pointer, returns a pointer to the
+ * corresponding payload.
+ */
+static void *header_to_payload(block_t *block)
+{
+ return (void *)(block->payload);
+}
+
+/* mm_checkheap: checks the heap for correctness; returns true if
+ * the heap is correct, and false otherwise.
+ * can call this function using mm_checkheap(__LINE__);
+ * to identify the line number of the call site.
+ */
+bool mm_checkheap(int lineno)
+{
+ (void)lineno;
+ if (heap_listp != NULL)
+ {
+ // check prologue footer: size is 0 and prologue is allocated
+ word_t prologue_footer = *find_prev_footer(heap_listp);
+ assert(extract_size(prologue_footer) == 0 && extract_alloc(prologue_footer));
+
+ // check header-footer consistency
+ block_t *block = heap_listp;
+ if (get_size(block) != 0)
+ {
+ word_t block_header = block->header;
+ word_t block_footer = *(find_prev_footer(find_next(heap_listp)));
+ assert(extract_size(block_header) == extract_size(block_footer));
+ assert(extract_alloc(block_header) == extract_alloc(block_footer));
+ }
+ }
+ return true;
+}
diff --git a/410user/libmalloc/memlib.c b/410user/libmalloc/memlib.c
new file mode 100644
index 0000000..8332559
--- /dev/null
+++ b/410user/libmalloc/memlib.c
@@ -0,0 +1,72 @@
+/* This should look a lot like 15-213 support code.
+ * Guess what...
+ */
+
+/* memlib.c - functions for modeling the memory system */
+/* $begin memlib */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <syscall.h>
+
+/* #define PAGE_SIZE 0x00001000 */
+/* #define PAGE_ALIGN_MASK 0xFFFFF000 */
+#define PAGE_ALIGN_MASK ((unsigned int) ~((unsigned int) (PAGE_SIZE-1)))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* private global variables */
+static char *mem_max_addr; /* max virtual address for the heap */
+static char *mem_brkp; /* Simulated brk pointer */
+static char *mem_alloctop; /* Maximum allocated address */
+
+extern void *_end; /* The end of the ELF binary address space */
+
+/*
+ * mem_init - initializes the memory system model
+ */
+void mem_init(int max_heap_addr)
+{
+ /* The max address for the heap. */
+ mem_max_addr = (char*)max_heap_addr;
+ mem_brkp = (char*)&_end + PAGE_SIZE;
+ mem_brkp = (char*)((int)mem_brkp & PAGE_ALIGN_MASK);
+ while (new_pages(mem_brkp, PAGE_SIZE))
+ mem_brkp += PAGE_SIZE;
+ mem_alloctop = mem_brkp + PAGE_SIZE;
+}
+
+/*
+ * mem_sbrk - simply uses the the sbrk function. Extends the heap
+ * by incr bytes and returns the start address of the new area. In
+ * this model, the heap cannot be shrunk.
+ */
+void *mem_sbrk(int incr)
+{
+ char *old_brk = mem_brkp;
+
+ /* Error check the request. */
+ if ( (incr < 0) || ((old_brk + incr) > mem_max_addr)) {
+ return (void *)NULL;
+ }
+
+ if (old_brk + incr > mem_alloctop) {
+ int allocincr = old_brk + incr - mem_alloctop;
+ allocincr += PAGE_SIZE - 1;
+ allocincr &= PAGE_ALIGN_MASK;
+
+ /* Issue a SBRK for more memory. */
+ if (new_pages((void*)mem_alloctop, allocincr)) {
+ return (void *)NULL;
+ }
+
+ mem_alloctop += allocincr;
+ }
+
+ mem_brkp += incr;
+
+ return (void *)old_brk;
+}
+/* $end memlib */
diff --git a/410user/libmalloc/memlib.h b/410user/libmalloc/memlib.h
new file mode 100644
index 0000000..b4b8a62
--- /dev/null
+++ b/410user/libmalloc/memlib.h
@@ -0,0 +1,13 @@
+/*
+ * memlib.h
+ * Modified for use in 15-410 at CMU
+ * Zachary Anderson(zra)
+ */
+
+#ifndef _MEMLIB_H
+#define _MEMLIB_H
+
+void *mem_init(int size);
+void *mem_sbrk(int incr);
+
+#endif /* _MEMLIB_H */
diff --git a/410user/libmalloc/user.mk b/410user/libmalloc/user.mk
new file mode 100644
index 0000000..1e92daa
--- /dev/null
+++ b/410user/libmalloc/user.mk
@@ -0,0 +1,7 @@
+410U_MALLOC_OBJS := malloc.o memlib.o
+410U_MALLOC_OBJS := $(410U_MALLOC_OBJS:%=$(410UDIR)/libmalloc/%)
+
+ALL_410UOBJS += $(410U_MALLOC_OBJS)
+410UCLEANS += $(410UDIR)/libmalloc.a
+
+$(410UDIR)/libmalloc.a: $(410U_MALLOC_OBJS)
diff --git a/410user/libsimics/simics.S b/410user/libsimics/simics.S
new file mode 100644
index 0000000..28c35dc
--- /dev/null
+++ b/410user/libsimics/simics.S
@@ -0,0 +1,14 @@
+/* simics.S - Simics interface (user side) */
+/* Copyright (c) 2014 Carnegie Mellon University */
+
+/* sim_call(ebx, ecx, edx) */
+.global sim_call
+sim_call:
+ push %ebx
+ mov 0x8(%esp), %ebx
+ mov 0xC(%esp), %ecx
+ mov 0x10(%esp), %edx
+ mov $0, %eax
+ xchg %ebx, %ebx
+ pop %ebx
+ ret
diff --git a/410user/libsimics/simics.h b/410user/libsimics/simics.h
new file mode 100644
index 0000000..f865d5a
--- /dev/null
+++ b/410user/libsimics/simics.h
@@ -0,0 +1,84 @@
+/** @file lib/simics.h
+ * @brief Simics interface (kernel side)
+ * @author matthewj S2008
+ */
+
+#ifndef LIB_SIMICS_H
+#define LIB_SIMICS_H
+
+#ifdef ASSEMBLER
+#define lprintf sim_printf
+#endif
+
+#define SIM_IN_SIMICS 0x04100000
+#define SIM_MEMSIZE 0x04100001
+#define SIM_PUTS 0x04100002
+#define SIM_BREAKPOINT 0x04100003
+#define SIM_HALT 0x04100004
+
+#define SIM_CK1 0x04108000
+#define SIM_FR_INKEYS 0x04108004
+#define SIM_FR_PROG 0x04108006
+#define SIM_FR_HERE 0x04108007
+
+#define SIM_TEST_REPORT 0x0410800B
+
+#ifdef ASSEMBLER
+
+/* Now *this* is a fun macro. It expands into a simics call to 'num' with
+ * arguments 'arg0' and 'arg1'. For use in assembly functions, to call simics
+ * without touching the stack. */
+
+#define INLINE_SIMCALL(num, arg0, arg1) \
+ mov $num, %ebx; \
+ mov arg0, %ecx; \
+ mov arg1, %edx; \
+ xchg %ebx, %ebx;
+
+#endif
+
+#ifndef ASSEMBLER
+
+#include <stdarg.h>
+
+/** @brief Calls simics. Arguments are ebx, ecx, edx. */
+extern int sim_call(int ebx, ...);
+
+/** @brief Returns whether we are in simics */
+extern int sim_in_simics(void);
+
+/** @brief Returns machine memory size, from simics */
+extern int sim_memsize(void);
+
+/** @brief Prints a string to the simics console */
+extern void sim_puts(const char *arg);
+
+/** @brief Breakpoint */
+extern void sim_breakpoint(void);
+
+/** @brief Halt the simulation */
+extern void sim_halt(void);
+
+/** @brief Run the checkpoint 1 checker. */
+extern void sim_ck1(void);
+
+/** @brief Grading harness stuff */
+extern void sim_fr_prog(int a);
+extern void sim_fr_here(void);
+
+/** @brief Convenience wrappers around sim_puts(). */
+extern void sim_vprintf(const char* fmt, va_list ap);
+extern void sim_printf(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
+
+/** @brief readline(), but wrapped in "magic" */
+int magic_readline(int size, char *buf);
+
+void sim_update_scoreboard(char *testname, int success);
+
+/* "Compatibility mode" for old code */
+#define MAGIC_BREAK sim_breakpoint()
+#define lprintf(...) sim_printf(__VA_ARGS__)
+
+#endif /* !ASSEMBLER */
+
+#endif /* !LIB_SIMICS_H */
diff --git a/410user/libsimics/simics_c.c b/410user/libsimics/simics_c.c
new file mode 100644
index 0000000..c32a298
--- /dev/null
+++ b/410user/libsimics/simics_c.c
@@ -0,0 +1,61 @@
+#include <simics.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <syscall.h> /* for readline() */
+
+int sim_in_simics(void) {
+ return sim_call(SIM_IN_SIMICS);
+}
+
+int sim_memsize(void) {
+ return sim_call(SIM_MEMSIZE);
+}
+
+void sim_puts(const char *arg) {
+ sim_call(SIM_PUTS, arg);
+}
+
+void sim_breakpoint(void) {
+ sim_call(SIM_BREAKPOINT);
+}
+
+void sim_halt(void) {
+ sim_call(SIM_HALT);
+}
+
+void sim_ck1(void) {
+ sim_call(SIM_CK1);
+}
+
+void sim_fr_prog(int a) {
+ sim_call(SIM_FR_PROG, a);
+}
+
+void sim_fr_here(void) {
+ sim_call(SIM_FR_HERE);
+}
+
+void sim_vprintf(const char* fmt, va_list ap)
+{
+ char str[256];
+ vsnprintf(str, sizeof(str) - 1, fmt, ap);
+ sim_puts(str);
+}
+
+void sim_printf(const char* fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sim_vprintf(fmt, ap);
+ va_end(ap);
+}
+
+void sim_update_scoreboard(char *testname, int success) {
+ sim_call(SIM_TEST_REPORT, testname, success);
+}
+
+int magic_readline(int size, char *buf) {
+ sim_call(SIM_FR_INKEYS);
+ return readline(size, buf);
+}
diff --git a/410user/libsimics/user.mk b/410user/libsimics/user.mk
new file mode 100644
index 0000000..a31bbaf
--- /dev/null
+++ b/410user/libsimics/user.mk
@@ -0,0 +1,10 @@
+410U_SIMICS_OBJS := \
+ simics.o \
+ simics_c.o
+
+410U_SIMICS_OBJS := $(410U_SIMICS_OBJS:%=$(410UDIR)/libsimics/%)
+
+ALL_410UOBJS += $(410U_SIMICS_OBJS)
+410UCLEANS += $(410UDIR)/libsimics.a
+
+$(410UDIR)/libsimics.a: $(410U_SIMICS_OBJS)
diff --git a/410user/libstdio/doprnt.c b/410user/libstdio/doprnt.c
new file mode 100644
index 0000000..548e626
--- /dev/null
+++ b/410user/libstdio/doprnt.c
@@ -0,0 +1,646 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <types.h>
+#include "doprnt.h"
+
+/*
+ * Common code for printf et al.
+ *
+ * The calling routine typically takes a variable number of arguments,
+ * and passes the address of the first one. This implementation
+ * assumes a straightforward, stack implementation, aligned to the
+ * machine's wordsize. Increasing addresses are assumed to point to
+ * successive arguments (left-to-right), as is the case for a machine
+ * with a downward-growing stack with arguments pushed right-to-left.
+ *
+ * To write, for example, fprintf() using this routine, the code
+ *
+ * fprintf(fd, format, args)
+ * FILE *fd;
+ * char *format;
+ * {
+ * _doprnt(format, &args, fd);
+ * }
+ *
+ * would suffice. (This example does not handle the fprintf's "return
+ * value" correctly, but who looks at the return value of fprintf
+ * anyway?)
+ *
+ * This version implements the following printf features:
+ *
+ * %d decimal conversion
+ * %u unsigned conversion
+ * %x hexadecimal conversion
+ * %X hexadecimal conversion with capital letters
+ * %o octal conversion
+ * %c character
+ * %s string
+ * %m.n field width, precision
+ * %-m.n left adjustment
+ * %0m.n zero-padding
+ * %*.* width and precision taken from arguments
+ *
+ * This version does not implement %f, %e, or %g. It accepts, but
+ * ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
+ * work correctly on machines for which sizeof(long) != sizeof(int).
+ * It does not even parse %D, %O, or %U; you should be using %ld, %o and
+ * %lu if you mean long conversion.
+ *
+ * As mentioned, this version does not return any reasonable value.
+ *
+ * Permission is granted to use, modify, or propagate this code as
+ * long as this notice is incorporated.
+ *
+ * Steve Summit 3/25/87
+ */
+
+/*
+ * Added formats for decoding device registers:
+ *
+ * printf("reg = %b", regval, "<base><arg>*")
+ *
+ * where <base> is the output base expressed as a control character:
+ * i.e. '\10' gives octal, '\20' gives hex. Each <arg> is a sequence of
+ * characters, the first of which gives the bit number to be inspected
+ * (origin 1), and the rest (up to a control character (<= 32)) give the
+ * name of the register. Thus
+ * printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
+ * would produce
+ * reg = 3<BITTWO,BITONE>
+ *
+ * If the second character in <arg> is also a control character, it
+ * indicates the last bit of a bit field. In this case, printf will extract
+ * bits <1> to <2> and print it. Characters following the second control
+ * character are printed before the bit field.
+ * printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
+ * would produce
+ * reg = b<FIELD1=2,BITONE>
+ */
+/*
+ * Added for general use:
+ * # prefix for alternate format:
+ * 0x (0X) for hex
+ * leading 0 for octal
+ * + print '+' if positive
+ * blank print ' ' if positive
+ *
+ * z signed hexadecimal
+ * r signed, 'radix'
+ * n unsigned, 'radix'
+ *
+ * D,U,O,Z same as corresponding lower-case versions
+ * (compatibility)
+ */
+/*
+ * Added ANSI %p for pointers. Output looks like 0x%08x.
+ */
+/*
+ *
+ * Added special for L4-use: %t format
+ *
+ * prints L4-threadids. standard format is "task.thread". Field-width
+ * may be specified with width-modifier. Padding begins with threadid,
+ * up to 2 chars, task-part follows.
+ *
+ * modifiers:
+ * # surrounds output with square brackets []
+ * l prints the high and low part of a threadid
+ * fixed length for the dwords: 8 chars
+ * 0 as usual, padding after optional '['
+ * - as usual
+ *
+ * Jork Loeser 9/20/99
+ */
+
+#define isdigit(d) ((d) >= '0' && (d) <= '9')
+#define Ctod(c) ((c) - '0')
+
+#define MAXBUF (sizeof(long int) * 8) /* enough for binary */
+
+static char digs[] = "0123456789abcdef";
+
+static void
+printnum(u, base, putc, putc_arg)
+ register unsigned long u; /* number to print */
+ register int base;
+ void (*putc)();
+ char *putc_arg;
+{
+ char buf[MAXBUF]; /* build number here */
+ register char * p = &buf[MAXBUF-1];
+
+ do {
+ *p-- = digs[u % base];
+ u /= base;
+ } while (u != 0);
+
+ while (++p != &buf[MAXBUF])
+ (*putc)(putc_arg, *p);
+}
+
+static void
+printnum_16(u, putc, putc_arg)
+ register unsigned long u; /* number to print */
+ void (*putc)();
+ char *putc_arg;
+{
+ char buf[8]; /* build number here */
+ register char * p = &buf[7];
+ int i;
+
+ for(i=0; i<8;i++){
+ *p-- = digs[u & 0x0f];
+ u >>= 4;
+ };
+
+ for(i=0;i<8;i++){
+ (*putc)(putc_arg, buf[i]);
+ }
+}
+
+boolean_t _doprnt_truncates = FALSE;
+
+void _doprnt(fmt, args, radix, putc, putc_arg)
+ register const char *fmt;
+ va_list args;
+ int radix; /* default radix - for '%r' */
+ void (*putc)(); /* character output */
+ char *putc_arg; /* argument for putc */
+{
+ int length;
+ int prec;
+ boolean_t ladjust;
+ char padc;
+ long long n, m;
+ unsigned long long u;
+ int plus_sign;
+ int sign_char;
+ boolean_t altfmt, truncate, upcase;
+ int base;
+ char c;
+ int longopt;
+
+ while (*fmt != '\0') {
+ if (*fmt != '%') {
+ (*putc)(putc_arg, *fmt++);
+ continue;
+ }
+
+ fmt++;
+
+ length = 0;
+ prec = -1;
+ ladjust = FALSE;
+ padc = ' ';
+ plus_sign = 0;
+ sign_char = 0;
+ altfmt = FALSE;
+ longopt = 0;
+
+ while (TRUE) {
+ if (*fmt == '#') {
+ altfmt = TRUE;
+ fmt++;
+ }
+ else if (*fmt == '-') {
+ ladjust = TRUE;
+ fmt++;
+ }
+ else if (*fmt == '+') {
+ plus_sign = '+';
+ fmt++;
+ }
+ else if (*fmt == ' ') {
+ if (plus_sign == 0)
+ plus_sign = ' ';
+ fmt++;
+ }
+ else
+ break;
+ }
+
+ if (*fmt == '0') {
+ padc = '0';
+ fmt++;
+ }
+
+ if (isdigit(*fmt)) {
+ while(isdigit(*fmt))
+ length = 10 * length + Ctod(*fmt++);
+ }
+ else if (*fmt == '*') {
+ length = va_arg(args, int);
+ fmt++;
+ if (length < 0) {
+ ladjust = !ladjust;
+ length = -length;
+ }
+ }
+
+ if (*fmt == '.') {
+ fmt++;
+ if (isdigit(*fmt)) {
+ prec = 0;
+ while(isdigit(*fmt))
+ prec = 10 * prec + Ctod(*fmt++);
+ }
+ else if (*fmt == '*') {
+ prec = va_arg(args, int);
+ fmt++;
+ }
+ }
+
+ while (*fmt == 'l'){
+ longopt++;
+ fmt++;
+ }
+
+ truncate = FALSE;
+ upcase = FALSE;
+
+ switch(*fmt) {
+ case 'b':
+ case 'B':
+ {
+ register char *p;
+ boolean_t any;
+ register int i;
+
+ u = va_arg(args, unsigned long);
+ p = va_arg(args, char *);
+ base = *p++;
+ printnum(u, base, putc, putc_arg);
+
+ if (u == 0)
+ break;
+
+ any = FALSE;
+ while ((i = *p++) != 0) {
+ /* NOTE: The '32' here is because ascii space */
+ if (*p <= 32) {
+ /*
+ * Bit field
+ */
+ register int j;
+ if (any)
+ (*putc)(putc_arg, ',');
+ else {
+ (*putc)(putc_arg, '<');
+ any = TRUE;
+ }
+ j = *p++;
+ for (; (c = *p) > 32; p++)
+ (*putc)(putc_arg, c);
+ printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
+ base, putc, putc_arg);
+ }
+ else if (u & (1<<(i-1))) {
+ if (any)
+ (*putc)(putc_arg, ',');
+ else {
+ (*putc)(putc_arg, '<');
+ any = TRUE;
+ }
+ for (; (c = *p) > 32; p++)
+ (*putc)(putc_arg, c);
+ }
+ else {
+ for (; *p > 32; p++)
+ continue;
+ }
+ }
+ if (any)
+ (*putc)(putc_arg, '>');
+ break;
+ }
+
+ case 'c':
+ c = va_arg(args, int);
+ (*putc)(putc_arg, c);
+ break;
+
+ case 't':
+ {
+ typedef struct {
+ unsigned version_low:10;
+ unsigned lthread:7;
+ unsigned task:11;
+ unsigned version_high:4;
+ unsigned site:17;
+ unsigned chief:11;
+ unsigned nest:4;
+ } tid_t;
+ typedef struct {
+ unsigned high;
+ unsigned low;
+ } lh_t;
+ union tid_t {
+ tid_t id;
+ lh_t lh;
+ } tid;
+
+ tid = va_arg(args, union tid_t);
+
+ if(longopt){
+
+ if(altfmt){
+ n = 19;
+ } else {
+ n = 17;
+ }
+
+ if (length > 0 && !ladjust) {
+ while(n < length){
+ putc(putc_arg, ' ');
+ n++;
+ }
+ }
+ if(altfmt) putc(putc_arg, '[');
+ printnum_16( tid.lh.high, putc, putc_arg);
+
+ putc(putc_arg, ':');
+
+ printnum_16( tid.lh.low, putc, putc_arg);
+
+ if(altfmt) putc(putc_arg, ']');
+
+ if(length > 0 && ladjust) {
+ while(n < length){
+ putc(putc_arg, ' ');
+ n++;
+ }
+ }
+
+ } else {
+
+ if(altfmt){
+ n = 4;
+ } else {
+ n = 2;
+ }
+
+ m = 1;
+
+ m += tid.id.lthread >= 0x10;
+ n += tid.id.task >= 0x10;
+ n += tid.id.task >= 0x100;
+
+ if (length > 0 && !ladjust && padc == ' ') {
+ while (n + 2 < length) {
+ (*putc)(putc_arg, ' ');
+ n++;
+ }
+ }
+
+ if(altfmt) (*putc)(putc_arg, '[');
+
+ if( length > 0 && !ladjust && padc == '0') {
+ while (n + 2 < length) {
+ putc(putc_arg, '0');
+ n++;
+ }
+ }
+
+ printnum(tid.id.task, 16, putc, putc_arg);
+ putc(putc_arg, '.');
+
+ if(length > 0 && !ladjust) {
+ while (n+m < length){
+ putc(putc_arg, padc);
+ n++;
+ }
+ }
+ printnum(tid.id.lthread, 16, putc, putc_arg);
+
+ if(altfmt) putc(putc_arg, ']');
+
+ if (n + m < length && ladjust) {
+ while (n + m < length) {
+ (*putc)(putc_arg, ' ');
+ n++;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 's':
+ {
+ register char *p;
+ register char *p2;
+
+ if (prec == -1)
+ prec = 0x7fffffff; /* MAXINT */
+
+ p = va_arg(args, char *);
+
+ if (p == (char *)0)
+ p = "";
+
+ if (length > 0 && !ladjust) {
+ n = 0;
+ p2 = p;
+
+ for (; *p != '\0' && n < prec; p++)
+ n++;
+
+ p = p2;
+
+ while (n < length) {
+ (*putc)(putc_arg, ' ');
+ n++;
+ }
+ }
+
+ n = 0;
+
+ while (*p != '\0') {
+ if (++n > prec)
+ break;
+
+ (*putc)(putc_arg, *p++);
+ }
+
+ if (n < length && ladjust) {
+ while (n < length) {
+ (*putc)(putc_arg, ' ');
+ n++;
+ }
+ }
+
+ break;
+ }
+
+
+ case 'o':
+ truncate = _doprnt_truncates;
+ case 'O':
+ base = 8;
+ goto print_unsigned;
+
+ case 'd':
+ truncate = _doprnt_truncates;
+ case 'D':
+ base = 10;
+ goto print_signed;
+
+ case 'u':
+ truncate = _doprnt_truncates;
+ case 'U':
+ base = 10;
+ goto print_unsigned;
+
+ case 'p':
+ padc = '0';
+ length = 8;
+ /*
+ * We do this instead of just setting altfmt to TRUE
+ * because we want 0 to have a 0x in front, and we want
+ * eight digits after the 0x -- not just 6.
+ */
+ (*putc)(putc_arg, '0');
+ (*putc)(putc_arg, 'x');
+ case 'x':
+ truncate = _doprnt_truncates;
+ base = 16;
+ goto print_unsigned;
+ case 'X':
+ base = 16;
+ upcase = TRUE;
+ goto print_unsigned;
+
+ case 'z':
+ truncate = _doprnt_truncates;
+ base = 16;
+ goto print_signed;
+ case 'Z':
+ base = 16;
+ upcase = TRUE;
+ goto print_signed;
+
+ case 'r':
+ truncate = _doprnt_truncates;
+ case 'R':
+ base = radix;
+ goto print_signed;
+
+ case 'n':
+ truncate = _doprnt_truncates;
+ case 'N':
+ base = radix;
+ goto print_unsigned;
+
+ print_signed:
+ if (longopt>1)
+ n = va_arg(args, long long);
+ else
+ n = va_arg(args, long);
+ if (n >= 0) {
+ u = n;
+ sign_char = plus_sign;
+ }
+ else {
+ u = -n;
+ sign_char = '-';
+ }
+ goto print_num;
+
+ print_unsigned:
+ if (longopt>1)
+ u = va_arg(args, unsigned long long);
+ else
+ u = va_arg(args, unsigned long);
+ goto print_num;
+
+ print_num:
+ {
+ char buf[MAXBUF]; /* build number here */
+ register char * p = &buf[MAXBUF-1];
+ static char ldigits[] = "0123456789abcdef";
+ static char udigits[] = "0123456789ABCDEF";
+ char *digits = ldigits;
+ char *prefix = 0;
+
+ if (truncate) u = (long)((int)(u));
+ if (upcase) digits = udigits;
+
+ if (u != 0 && altfmt) {
+ if (base == 8)
+ prefix = "0";
+ else if (base == 16)
+ prefix = "0x";
+ }
+
+ do {
+ *p-- = digits[u % base];
+ u /= base;
+ } while (u != 0);
+
+ length -= (&buf[MAXBUF-1] - p);
+ if (sign_char)
+ length--;
+ if (prefix)
+ length -= strlen(prefix);
+
+ if (padc == ' ' && !ladjust) {
+ /* blank padding goes before prefix */
+ while (--length >= 0)
+ (*putc)(putc_arg, ' ');
+ }
+ if (sign_char)
+ (*putc)(putc_arg, sign_char);
+ if (prefix)
+ while (*prefix)
+ (*putc)(putc_arg, *prefix++);
+ if (padc == '0') {
+ /* zero padding goes after sign and prefix */
+ while (--length >= 0)
+ (*putc)(putc_arg, '0');
+ }
+ while (++p != &buf[MAXBUF])
+ (*putc)(putc_arg, *p);
+
+ if (ladjust) {
+ while (--length >= 0)
+ (*putc)(putc_arg, ' ');
+ }
+ break;
+ }
+
+ case '\0':
+ fmt--;
+ break;
+
+ default:
+ (*putc)(putc_arg, *fmt);
+ }
+ fmt++;
+ }
+}
diff --git a/410user/libstdio/doprnt.h b/410user/libstdio/doprnt.h
new file mode 100644
index 0000000..d2bc0f5
--- /dev/null
+++ b/410user/libstdio/doprnt.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1996 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#ifndef __DOPRNT_H_INCLUDED__
+#define __DOPRNT_H_INCLUDED__
+
+#include <stdarg.h>
+
+void _doprnt(
+ register const char *fmt,
+ va_list args,
+ int radix, /* default radix - for '%r' */
+ void (*putc)(), /* character output */
+ char *putc_arg); /* argument for putc */
+
+#endif /* __DOPRNT_H_INCLUDED__ */
diff --git a/410user/libstdio/doscan.c b/410user/libstdio/doscan.c
new file mode 100644
index 0000000..f4c0a30
--- /dev/null
+++ b/410user/libstdio/doscan.c
@@ -0,0 +1,181 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: sscanf.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 3/93
+ *
+ * Parse trivially simple strings
+ */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <types.h>
+#include <ctype.h>
+#include "doscan.h"
+
+/*
+ * All I need is a miracle ...
+ * to keep this from growing like all the other sscanf!
+ */
+int
+_doscan(const char *fmt, va_list vp,
+ int (*getc)(void *getc_arg),
+ void (*ungetc)(int c, void *getc_arg),
+ void *getc_arg)
+{
+ register int c;
+ boolean_t neg;
+ boolean_t discard;
+ boolean_t invalid;
+ int vals = 0;
+
+ while ((c = *fmt++) != 0) {
+
+ if (c != '%') {
+ if (isspace(c))
+ {
+ while (isspace(c = getc(getc_arg)));
+ if (c == 0) break;
+ ungetc(c, getc_arg);
+ continue;
+ }
+ else if (c == getc(getc_arg))
+ continue;
+ else
+ break; /* mismatch */
+ }
+
+ discard = 0;
+ invalid = 1;
+
+ more_fmt:
+
+ c = getc(getc_arg);
+ if (c == 0)
+ break; /* end of input */
+
+ switch (*fmt++) {
+
+ case 'd':
+ {
+ long n = 0;
+
+ neg = c == '-';
+ if (neg) c = getc(getc_arg);
+
+ while (c >= '0' && c <= '9') {
+ n = n * 10 + (c - '0');
+ c = getc(getc_arg);
+ invalid = 0;
+ }
+ ungetc(c, getc_arg);
+
+ if (neg) n = -n;
+
+ /* done, store it away */
+ if (!discard)
+ {
+ int *p = va_arg(vp, int *);
+ *p = n;
+ }
+
+ break;
+ }
+
+ case 'x':
+ {
+ long n = 0;
+
+ neg = c == '-';
+ if (neg) c = getc(getc_arg);
+
+ while (1)
+ {
+ if ((c >= '0') && (c <= '9'))
+ n = n * 16 + (c - '0');
+ else if ((c >= 'a') && (c <= 'f'))
+ n = n * 16 + (c - 'a' + 10);
+ else if ((c >= 'A') && (c <= 'F'))
+ n = n * 16 + (c - 'A' + 10);
+ else
+ break;
+ c = getc(getc_arg);
+ invalid = 0;
+ }
+ ungetc(c, getc_arg); /* retract lookahead */
+
+ if (neg) n = -n;
+
+ /* done, store it away */
+ if (!discard)
+ {
+ int *p = va_arg(vp, int *);
+ *p = n;
+ }
+
+ break;
+ }
+
+ case 's':
+ {
+ char *buf = NULL;
+
+ if (!discard)
+ buf = va_arg(vp, char *);
+
+ while (c && !isspace(c))
+ {
+ if (!discard)
+ *buf++ = c;
+ c = getc(getc_arg);
+ invalid = 0;
+ }
+ ungetc(c, getc_arg); /* retract lookahead */
+
+ if (!discard)
+ *buf = 0;
+
+ break;
+ }
+
+ case '*':
+ discard = 1;
+ goto more_fmt;
+
+ default:
+ break;
+ }
+
+ if (invalid)
+ break;
+ else if (!discard)
+ vals++;
+ }
+
+ return vals;
+}
+
diff --git a/410user/libstdio/doscan.h b/410user/libstdio/doscan.h
new file mode 100644
index 0000000..4973186
--- /dev/null
+++ b/410user/libstdio/doscan.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 1996 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#ifndef __DOSCAN_H_INCLUDED__
+#define __DOSCAN_H_INCLUDED__
+
+int _doscan(const char *fmt, va_list vp,
+ int (*getc)(void *getc_arg),
+ void (*ungetc)(int c, void *getc_arg),
+ void *getc_arg);
+
+#endif /* __DOSCAN_H_INCLUDED__ */
diff --git a/410user/libstdio/hexdump.c b/410user/libstdio/hexdump.c
new file mode 100644
index 0000000..636f21c
--- /dev/null
+++ b/410user/libstdio/hexdump.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1996 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+
+/*
+ * Print a buffer hexdump style. Example:
+ *
+ * .---------------------------------------------------------------------------.
+ * | 00000000 2e2f612e 6f757400 5445524d 3d787465 ./a.out.TERM=xte |
+ * | 00000010 726d0048 4f4d453d 2f616673 2f63732e rm.HOME=/afs/cs. |
+ * | 00000020 75746168 2e656475 2f686f6d 652f6c6f utah.edu/home/lo |
+ * | 00000030 6d657700 5348454c 4c3d2f62 696e2f74 mew.SHELL=/bin/t |
+ * | 00000040 63736800 4c4f474e 414d453d 6c6f6d65 csh.LOGNAME=lome |
+ * | 00000050 77005553 45523d6c 6f6d6577 00504154 w.USER=lomew.PAT |
+ * | 00000060 483d2f61 66732f63 732e7574 61682e65 H=/afs/cs.utah.e |
+ * | 00000070 64752f68 6f6d652f 6c6f6d65 772f6269 du/home/lomew/bi |
+ * | 00000080 6e2f4073 79733a2f 6166732f 63732e75 n/@sys:/afs/cs.u |
+ * | 00000090 7461682e 6564 tah.ed |
+ * `---------------------------------------------------------------------------'
+ *
+ * It might be useful to have an option for printing out little-endianly.
+ * Adapted from Godmar's hook.c.
+ */
+void
+hexdump(void *buf, int len)
+{
+ int i, j;
+ char *b = (char *)buf;
+
+ printf(".---------------------------------------------------------------------------.\n");
+ for (i = 0; i < len; i += 16) {
+ printf("| %08x ", i);
+ for (j = i; j < i+16; j++) {
+ if (j % 4 == 0)
+ printf(" ");
+ if (j >= len)
+ printf(" ");
+ else
+ printf("%02x", (unsigned char)b[j]);
+ }
+
+ printf(" ");
+ for (j = i; j < i+16; j++)
+ if (j >= len)
+ printf(" ");
+ else
+ printf("%c", isgraph(b[j]) ? b[j] : '.');
+ printf(" |\n");
+ }
+ printf("`---------------------------------------------------------------------------'\n");
+}
diff --git a/410user/libstdio/printf.c b/410user/libstdio/printf.c
new file mode 100644
index 0000000..0a4a4db
--- /dev/null
+++ b/410user/libstdio/printf.c
@@ -0,0 +1,97 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1989 Carnegie Mellon University.
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <syscall.h>
+#include "doprnt.h"
+
+/* This version of printf is implemented in terms of putchar and puts. */
+
+#define PRINTF_BUFMAX 128
+
+struct printf_state {
+ char buf[PRINTF_BUFMAX];
+ unsigned int index;
+};
+
+static void
+flush(struct printf_state *state)
+{
+ print(state->index, state->buf);
+ state->index = 0;
+}
+
+static void
+printf_char(char *arg, int c)
+{
+ struct printf_state *state = (struct printf_state *) arg;
+
+ if (state->index >= PRINTF_BUFMAX) {
+ flush(state);
+ }
+
+ state->buf[state->index] = c;
+ state->index++;
+ if (c == '\n') {
+ flush(state);
+ }
+}
+
+/*
+ * Printing (to console)
+ */
+int vprintf(const char *fmt, va_list args)
+{
+ struct printf_state state;
+
+ state.index = 0;
+ _doprnt(fmt, args, 0, (void (*)())printf_char, (char *) &state);
+
+ if (state.index != 0)
+ flush(&state);
+
+ /* _doprnt currently doesn't pass back error codes,
+ so just assume nothing bad happened. */
+ return 0;
+}
+
+int
+printf(const char *fmt, ...)
+{
+ va_list args;
+ int err;
+
+ va_start(args, fmt);
+ err = vprintf(fmt, args);
+ va_end(args);
+
+ return err;
+}
+
diff --git a/410user/libstdio/putchar.c b/410user/libstdio/putchar.c
new file mode 100644
index 0000000..4dd8421
--- /dev/null
+++ b/410user/libstdio/putchar.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1995 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+/* 15-410 mods by de0u 2008-09-02 ... */
+#include <stdio.h>
+#include <syscall.h>
+
+int putchar(int c)
+{
+ print( 1, (char *)&c );
+ return c;
+}
+
diff --git a/410user/libstdio/puts.c b/410user/libstdio/puts.c
new file mode 100644
index 0000000..d27a070
--- /dev/null
+++ b/410user/libstdio/puts.c
@@ -0,0 +1,14 @@
+/** @file 410user/libstdio/puts.c
+ * @author elly1 S2010
+ * @brief The puts() libc function
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+int puts(const char *s) {
+ print(strlen(s), (char *)s);
+ putchar('\n');
+ return 0;
+}
diff --git a/410user/libstdio/sprintf.c b/410user/libstdio/sprintf.c
new file mode 100644
index 0000000..c667837
--- /dev/null
+++ b/410user/libstdio/sprintf.c
@@ -0,0 +1,104 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <stdarg.h>
+#include "doprnt.h"
+
+#define SPRINTF_UNLIMITED -1
+struct sprintf_state {
+ char *buf;
+ unsigned int len;
+ unsigned int max;
+};
+
+static void
+savechar(char *arg, int c)
+{
+ struct sprintf_state *state = (struct sprintf_state *)arg;
+
+ if (state->max != (unsigned int)SPRINTF_UNLIMITED)
+ {
+ if (state->len >= state->max) {
+ state->len++;
+ return;
+ }
+ }
+
+ state->len++;
+ *state->buf = c;
+ state->buf++;
+}
+
+int vsprintf(char *s, const char *fmt, va_list args)
+{
+ struct sprintf_state state;
+ state.max = SPRINTF_UNLIMITED;
+ state.len = 0;
+ state.buf = s;
+
+ _doprnt(fmt, args, 0, (void (*)()) savechar, (char *) &state);
+ *(state.buf) = '\0';
+
+ return state.len;
+}
+
+int vsnprintf(char *s, int size, const char *fmt, va_list args)
+{
+ struct sprintf_state state;
+ state.max = size - 1;
+ state.len = 0;
+ state.buf = s;
+
+ _doprnt(fmt, args, 0, (void (*)()) savechar, (char *) &state);
+ *(state.buf) = '\0';
+
+ return state.len;
+}
+
+int sprintf(char *s, const char *fmt, ...)
+{
+ va_list args;
+ int err;
+
+ va_start(args, fmt);
+ err = vsprintf(s, fmt, args);
+ va_end(args);
+
+ return err;
+}
+
+int snprintf(char *s, int size, const char *fmt, ...)
+{
+ va_list args;
+ int err;
+
+ va_start(args, fmt);
+ err = vsnprintf(s, size, fmt, args);
+ va_end(args);
+
+ return err;
+}
+
diff --git a/410user/libstdio/sscanf.c b/410user/libstdio/sscanf.c
new file mode 100644
index 0000000..7f48ea9
--- /dev/null
+++ b/410user/libstdio/sscanf.c
@@ -0,0 +1,65 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <stdarg.h>
+#include "doscan.h"
+
+static int
+readchar(arg)
+ void *arg;
+{
+ return *(*(unsigned char**)arg)++;
+}
+
+static void
+unchar(c, arg)
+ int c;
+ void *arg;
+{
+ (void)c;
+ (*(unsigned char**)arg)--;
+}
+
+int vsscanf(s, fmt, args)
+ char *s;
+ char *fmt;
+ va_list args;
+{
+ return _doscan(fmt, args, readchar, unchar, &s);
+}
+
+int sscanf(char *s, char *fmt, ...)
+{
+ va_list args;
+ int vals;
+
+ va_start(args, fmt);
+ vals = vsscanf(s, fmt, args);
+ va_end(args);
+
+ return vals;
+}
+
diff --git a/410user/libstdio/stdio.h b/410user/libstdio/stdio.h
new file mode 100644
index 0000000..b25b899
--- /dev/null
+++ b/410user/libstdio/stdio.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1996-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+#ifndef _FLUX_MC_STDIO_H
+#define _FLUX_MC_STDIO_H
+
+#ifndef ASSEMBLER
+#include <stddef.h> /* For size_t, NULL */
+#include <stdarg.h>
+#include <types.h>
+
+int putchar(int __c);
+int puts(const char *__str);
+int printf(const char *__format, ...)
+ __attribute__((__format__ (__printf__, 1, 2)));
+int vprintf(const char *__format, va_list __vl);
+int sprintf(char *__dest, const char *__format, ...)
+ __attribute__((__format__ (__printf__, 2, 3)));
+int snprintf(char *__dest, size_t __size, const char *__format, ...)
+ __attribute__((__format__ (__printf__, 3, 4)));
+int vsprintf(char *__dest, const char *__format, va_list __vl);
+int vsnprintf(char *__dest, size_t __size, const char *__format, va_list __vl);
+int sscanf(const char *__str, const char *__format, ...)
+ __attribute__((__format__ (__scanf__, 2, 3)));
+void hexdump(void *buf, int len);
+
+#endif /* !ASSEMBLER */
+
+#endif /* _FLUX_MC_STDIO_H */
diff --git a/410user/libstdio/user.mk b/410user/libstdio/user.mk
new file mode 100644
index 0000000..f9bdcf0
--- /dev/null
+++ b/410user/libstdio/user.mk
@@ -0,0 +1,16 @@
+410ULIB_STDIO_OBJS := \
+ doprnt.o \
+ doscan.o \
+ hexdump.o \
+ printf.o \
+ putchar.o \
+ puts.o \
+ sprintf.o \
+ sscanf.o \
+
+410ULIB_STDIO_OBJS := $(410ULIB_STDIO_OBJS:%=$(410UDIR)/libstdio/%)
+
+ALL_410UOBJS += $(410ULIB_STDIO_OBJS)
+410UCLEANS += $(410UDIR)/libstdio.a
+
+$(410UDIR)/libstdio.a: $(410ULIB_STDIO_OBJS)
diff --git a/410user/libstdlib/abs.c b/410user/libstdlib/abs.c
new file mode 100644
index 0000000..3892eec
--- /dev/null
+++ b/410user/libstdlib/abs.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <stdlib.h>
+
+#undef abs
+
+int abs(int val)
+{
+ return val >= 0 ? val : -val;
+}
+
diff --git a/410user/libstdlib/atol.c b/410user/libstdlib/atol.c
new file mode 100644
index 0000000..30f976d
--- /dev/null
+++ b/410user/libstdlib/atol.c
@@ -0,0 +1,9 @@
+#include <stddef.h>
+#include <stdlib.h>
+
+long
+atol(const char *str)
+{
+ return strtol(str, NULL, 10);
+}
+
diff --git a/410user/libstdlib/ctype.c b/410user/libstdlib/ctype.c
new file mode 100644
index 0000000..2159f5a
--- /dev/null
+++ b/410user/libstdlib/ctype.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 1996-1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+int isascii(int c)
+{
+ return ((c) >= 0) && ((c) <= 126);
+}
+
+int iscntrl(int c)
+{
+ return ((c) < ' ') || ((c) > 126);
+}
+
+int isdigit(int c)
+{
+ return ((c) >= '0') && ((c) <= '9');
+}
+
+int isgraph(int c)
+{
+ return ((c) > ' ') && ((c) <= 126);
+}
+
+int islower(int c)
+{
+ return (c >= 'a') && (c <= 'z');
+}
+
+int isprint(int c)
+{
+ return ((c) >= ' ') && ((c) <= 126);
+}
+
+int isspace(int c)
+{
+ return ((c) == ' ') || ((c) == '\f')
+ || ((c) == '\n') || ((c) == '\r')
+ || ((c) == '\t') || ((c) == '\v');
+}
+
+int isupper(int c)
+{
+ return (c >= 'A') && (c <= 'Z');
+}
+
+int isxdigit(int c)
+{
+ return isdigit(c) ||
+ ((c >= 'A') && (c <= 'F')) ||
+ ((c >= 'a') && (c <= 'f'));
+}
+
+int isalpha(int c)
+{
+ return islower(c) || isupper(c);
+}
+
+int isalnum(int c)
+{
+ return isalpha(c) || isdigit(c);
+}
+
+int ispunct(int c)
+{
+ return isgraph(c) && !isalnum(c);
+}
+
+int toupper(int c)
+{
+ return ((c >= 'a') && (c <= 'z')) ? (c - 'a' + 'A') : c;
+}
+
+int tolower(int c)
+{
+ return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c;
+}
diff --git a/410user/libstdlib/ctype.h b/410user/libstdlib/ctype.h
new file mode 100644
index 0000000..72eaa20
--- /dev/null
+++ b/410user/libstdlib/ctype.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1996-1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+#ifndef _FLUX_MC_CTYPE_H_
+#define _FLUX_MC_CTYPE_H_
+
+int isascii(int c);
+int iscntrl(int c);
+int isdigit(int c);
+int isgraph(int c);
+int islower(int c);
+int isprint(int c);
+int isspace(int c);
+int isupper(int c);
+int isxdigit(int c);
+int isalpha(int c);
+int isalnum(int c);
+int ispunct(int c);
+int toupper(int c);
+int tolower(int c);
+
+
+#endif /* _FLUX_MC_CTYPE_H_ */
diff --git a/410user/libstdlib/exit.c b/410user/libstdlib/exit.c
new file mode 100644
index 0000000..4fab152
--- /dev/null
+++ b/410user/libstdlib/exit.c
@@ -0,0 +1,15 @@
+/*
+ * exit.c
+ * For new set_status()/vanish() interface, Spring 2007
+ * @author Dave Eckhardt (de0u)
+ */
+
+#include <syscall.h>
+
+void set_status(int status);
+void vanish(void) NORETURN;
+
+void exit(int status)
+{
+ task_vanish(status);
+}
diff --git a/410user/libstdlib/qsort.c b/410user/libstdlib/qsort.c
new file mode 100644
index 0000000..3c00eb6
--- /dev/null
+++ b/410user/libstdlib/qsort.c
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <types.h>
+#include <stdlib.h>
+
+static inline char *med3(char *, char *, char *, int (*)());
+static inline void swapfunc(char *, char *, int, int);
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ register TYPE *pi = (TYPE *) (parmi); \
+ register TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ register TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static inline void
+swapfunc(a, b, n, swaptype)
+ char *a, *b;
+ int n, swaptype;
+{
+ if(swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+static inline char *
+med3(a, b, c, cmp)
+ char *a, *b, *c;
+ int (*cmp)();
+{
+ return cmp(a, b) < 0 ?
+ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
+ :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
+}
+
+void
+qsort(a, n, es, cmp)
+ void *a;
+ size_t n, es;
+ int (*cmp)();
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype, swap_cnt;
+
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = a + (n / 2) * es;
+ if (n > 7) {
+ pl = a;
+ pn = a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp);
+ pm = med3(pm - d, pm, pm + d, cmp);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp);
+ }
+ pm = med3(pl, pm, pn, cmp);
+ }
+ swap(a, pm);
+ pa = pb = a + es;
+
+ pc = pd = a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a)) <= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+
+ pn = a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = min(pd - pc, pn - pd - (int)es);
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > (int)es)
+ qsort(a, r / es, es, cmp);
+ if ((r = pd - pc) > (int)es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+/* qsort(pn - r, r / es, es, cmp);*/
+}
diff --git a/410user/libstdlib/rand.c b/410user/libstdlib/rand.c
new file mode 100644
index 0000000..fcff0b5
--- /dev/null
+++ b/410user/libstdlib/rand.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <stdlib.h>
+
+static unsigned seed[2];
+
+int
+rand(void)
+{
+ seed[0] += 0xa859c317;
+ seed[0] += (seed[1] << 13) | (seed[1] >> 19);
+ seed[1] += seed[0];
+ return seed[0] & 0x7FFFFFFF;
+}
+
+void
+srand(unsigned new_seed)
+{
+ seed[0] = seed[1] = new_seed;
+}
+
+#if 0 /* test code */
+
+#define CYCLES 100000000
+
+void main(int argc, char **argv)
+{
+ unsigned orig_seed = atol(argv[1]);
+ int i;
+
+ srand(orig_seed);
+ for(i = 0; i < CYCLES; i++)
+ {
+ int r = rand();
+ /*printf("%08x\n", r);*/
+ if ((seed[0] == orig_seed) && (seed[1] == orig_seed))
+ {
+ printf("repeates after %d cycles\n", i);
+ exit(0);
+ }
+ }
+ printf("still not repeating after %d cycles\n", CYCLES);
+}
+
+#endif
+
diff --git a/410user/libstdlib/stdlib.h b/410user/libstdlib/stdlib.h
new file mode 100644
index 0000000..a30aa65
--- /dev/null
+++ b/410user/libstdlib/stdlib.h
@@ -0,0 +1,30 @@
+#ifndef _STDLIB_H_
+#define _STDLIB_H_
+
+#include <stddef.h> /* For size_t, NULL */
+#include <malloc.h> /* "Listen to what the man says" */
+
+/* start user-land only */
+
+/* Apologies for the gcc-ism, but gcc gets angry w/o it */
+void exit(int status) __attribute__((__noreturn__));
+
+/* end user-land only */
+
+long atol(const char *__str);
+#define atoi(str) ((int)atol(str))
+
+long strtol(const char *__p, char **__out_p, int __base);
+unsigned long strtoul(const char *__p, char **__out_p, int __base);
+
+#define RAND_MAX ((signed int)0x7fffffff)
+int rand(void);
+void srand(unsigned new_seed);
+
+int abs(int val);
+
+void qsort(void *a, size_t n, size_t es, int (*cmp)(char*, char*));
+
+void panic(const char *, ...);
+
+#endif
diff --git a/410user/libstdlib/strtol.c b/410user/libstdlib/strtol.c
new file mode 100644
index 0000000..90c4ef4
--- /dev/null
+++ b/410user/libstdlib/strtol.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+long strtol(const char *p, char **out_p, int base)
+{
+ long v = 0;
+ int is_neg = 0;
+
+ while (isspace(*p))
+ p++;
+ if (*p == '-')
+ is_neg = 1, p++;
+ else if (*p == '+')
+ is_neg = 0;
+ if (((base == 16) || (base == 0)) &&
+ ((*p == '0') && ((p[1] == 'x') || (p[1] == 'X'))))
+ {
+ p += 2;
+ base = 16;
+ }
+ if (base == 0)
+ {
+ if (*p == '0')
+ base = 8;
+ else
+ base = 10;
+ }
+ while (1)
+ {
+ char c = *p;
+ if ((c >= '0') && (c <= '9') && (c - '0' < base))
+ v = (v * base) + (c - '0');
+ else if ((c >= 'a') && (c <= 'z') && (c - 'a' + 10 < base))
+ v = (v * base) + (c - 'a' + 10);
+ else if ((c >= 'A') && (c <= 'Z') && (c - 'A' + 10 < base))
+ v = (v * base) + (c - 'A' + 10);
+ else
+ break;
+ p++;
+ }
+ if (is_neg)
+ v = -v;
+ if (out_p) *out_p = (char*)p;
+ return v;
+}
+
diff --git a/410user/libstdlib/strtoul.c b/410user/libstdlib/strtoul.c
new file mode 100644
index 0000000..59d8f2a
--- /dev/null
+++ b/410user/libstdlib/strtoul.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+unsigned long strtoul(const char *p, char **out_p, int base)
+{
+ unsigned long v = 0;
+
+ while (isspace(*p))
+ p++;
+ if (((base == 16) || (base == 0)) &&
+ ((*p == '0') && ((p[1] == 'x') || (p[1] == 'X'))))
+ {
+ p += 2;
+ base = 16;
+ }
+ if (base == 0)
+ {
+ if (*p == '0')
+ base = 8;
+ else
+ base = 10;
+ }
+ while (1)
+ {
+ char c = *p;
+ if ((c >= '0') && (c <= '9') && (c - '0' < base))
+ v = (v * base) + (c - '0');
+ else if ((c >= 'a') && (c <= 'z') && (c - 'a' + 10 < base))
+ v = (v * base) + (c - 'a' + 10);
+ else if ((c >= 'A') && (c <= 'Z') && (c - 'A' + 10 < base))
+ v = (v * base) + (c - 'A' + 10);
+ else
+ break;
+ p++;
+ }
+
+ if (out_p) *out_p = (char*)p;
+ return v;
+}
+
diff --git a/410user/libstdlib/user.mk b/410user/libstdlib/user.mk
new file mode 100644
index 0000000..e1ed87f
--- /dev/null
+++ b/410user/libstdlib/user.mk
@@ -0,0 +1,17 @@
+410ULIB_STDLIB_OBJS := \
+ abs.o \
+ atol.o \
+ ctype.o \
+ exit.o \
+ qsort.o \
+ rand.o \
+ strtol.o \
+ strtoul.o \
+
+
+410ULIB_STDLIB_OBJS := $(410ULIB_STDLIB_OBJS:%=$(410UDIR)/libstdlib/%)
+
+ALL_410UOBJS += $(410ULIB_STDLIB_OBJS)
+410UCLEANS += $(410UDIR)/libstdlib.a
+
+$(410UDIR)/libstdlib.a: $(410ULIB_STDLIB_OBJS)
diff --git a/410user/libstring/memcmp.c b/410user/libstring/memcmp.c
new file mode 100644
index 0000000..204fd4b
--- /dev/null
+++ b/410user/libstring/memcmp.c
@@ -0,0 +1,53 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: limach/memcmp.c
+ * Author: Robert V. Baron at Carnegie Mellon
+ * Date: Oct 13, 1992
+ * Abstract:
+ * strcmp (s1, s2) compares the strings "s1" and "s2".
+ * It returns 0 if the strings are identical. It returns
+ * > 0 if the first character that differs into two strings
+ * is larger in s1 than in s2 or if s1 is longer than s2 and
+ * the contents are identical up to the length of s2.
+ * It returns < 0 if the first differing character is smaller
+ * in s1 than in s2 or if s1 is shorter than s2 and the
+ * contents are identical upto the length of s1.
+ */
+
+int
+memcmp(const void *s1v, const void *s2v, int size)
+{
+ register const char *s1 = s1v, *s2 = s2v;
+ register unsigned int a, b;
+
+ while (size-- > 0) {
+ if ((a = *s1++) != (b = *s2++))
+ return (a-b);
+ }
+
+ return 0;
+}
diff --git a/410user/libstring/memset.c b/410user/libstring/memset.c
new file mode 100644
index 0000000..6a40159
--- /dev/null
+++ b/410user/libstring/memset.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1995 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <types.h>
+
+void *
+memset(void *tov, int c, size_t len)
+{
+ register char *to = tov;
+
+ while (len-- > 0)
+ *to++ = c;
+
+ return tov;
+}
+
diff --git a/410user/libstring/rindex.c b/410user/libstring/rindex.c
new file mode 100644
index 0000000..847b3dc
--- /dev/null
+++ b/410user/libstring/rindex.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+char *rindex(const char *s, int c)
+{
+ char *it = 0;
+
+ while (1)
+ {
+ if (*s == c)
+ it = (char *)s;
+ if (*s == 0)
+ return it;
+ s++;
+ }
+}
+
diff --git a/410user/libstring/strcat.c b/410user/libstring/strcat.c
new file mode 100644
index 0000000..b0906a0
--- /dev/null
+++ b/410user/libstring/strcat.c
@@ -0,0 +1,38 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+char *
+strcat(s, add)
+register char *s, *add;
+{
+register char *ret = s;
+
+ while (*s) s++;
+
+ while ((*s++ = *add++) != 0);
+
+ return ret;
+}
diff --git a/410user/libstring/strchr.c b/410user/libstring/strchr.c
new file mode 100644
index 0000000..5eff9e5
--- /dev/null
+++ b/410user/libstring/strchr.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1995 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <string.h>
+
+char *strchr(const char *s, int c)
+{
+ while (1)
+ {
+ if (*s == c)
+ return (char*)s;
+ if (*s == 0)
+ return 0;
+ s++;
+ }
+}
+
diff --git a/410user/libstring/strcmp.c b/410user/libstring/strcmp.c
new file mode 100644
index 0000000..77cd82d
--- /dev/null
+++ b/410user/libstring/strcmp.c
@@ -0,0 +1,55 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: limach/strcmp.c
+ * Author: Robert V. Baron at Carnegie Mellon
+ * Date: Oct 13, 1992
+ * Abstract:
+ * strcmp (s1, s2) compares the strings "s1" and "s2".
+ * It returns 0 if the strings are identical. It returns
+ * > 0 if the first character that differs into two strings
+ * is larger in s1 than in s2 or if s1 is longer than s2 and
+ * the contents are identical up to the length of s2.
+ * It returns < 0 if the first differing character is smaller
+ * in s1 than in s2 or if s1 is shorter than s2 and the
+ * contents are identical upto the length of s1.
+ */
+
+int
+strcmp(s1,s2)
+register unsigned char *s1, *s2;
+{
+register unsigned int a, b;
+
+
+
+ while ( (a = *s1++), (b = *s2++), a && b) {
+ if (a != b)
+ return (a-b);
+ }
+
+ return a-b;
+}
diff --git a/410user/libstring/strcpy.c b/410user/libstring/strcpy.c
new file mode 100644
index 0000000..66df3b9
--- /dev/null
+++ b/410user/libstring/strcpy.c
@@ -0,0 +1,45 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: libmach_sa/strcpy.c
+ * Author: Robert V. Baron at Carnegie Mellon
+ * Date: Oct 13, 1992
+ * Abstract:
+ * strcpy copies the contents of the string "from" including
+ * the null terminator to the string "to". A pointer to "to"
+ * is returned.
+ */
+
+char *
+strcpy(to,from)
+register char *to, *from;
+{
+register char *ret = to;
+
+ while ((*to++ = *from++) != 0);
+
+ return ret;
+}
diff --git a/410user/libstring/strcspn.c b/410user/libstring/strcspn.c
new file mode 100644
index 0000000..97b2c91
--- /dev/null
+++ b/410user/libstring/strcspn.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <types.h>
+#include <string.h>
+
+/*
+ * Span the complement of string s2.
+ */
+size_t
+strcspn(s1, s2)
+ const char *s1;
+ register const char *s2;
+{
+ register const char *p, *spanp;
+ register char c, sc;
+
+ /*
+ * Stop as soon as we find any character from s2. Note that there
+ * must be a NUL in s2; it suffices to stop when we find that, too.
+ */
+ for (p = s1;;) {
+ c = *p++;
+ spanp = s2;
+ do {
+ if ((sc = *spanp++) == c)
+ return (p - 1 - s1);
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/410user/libstring/strdup.c b/410user/libstring/strdup.c
new file mode 100644
index 0000000..7275355
--- /dev/null
+++ b/410user/libstring/strdup.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+
+
+char *strdup(const char *src)
+{
+ char *buf = malloc(strlen(src)+1);
+ if (buf)
+ strcpy(buf, src);
+ return buf;
+}
+
diff --git a/410user/libstring/string.h b/410user/libstring/string.h
new file mode 100644
index 0000000..e47934a
--- /dev/null
+++ b/410user/libstring/string.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+#ifndef _FLUX_MC_STRING_H_
+#define _FLUX_MC_STRING_H_
+
+#include <types.h>
+
+size_t strlen(const char *__s);
+char *strcpy(char *__dest, const char *__src);
+char *strncpy(char *__dest, const char *__src, size_t __n);
+char *strdup(const char *__s);
+char *strcat(char *__dest, const char *__src);
+char *strncat(char *__dest, const char *__src, size_t __n);
+int strcmp(const char *__a, const char *__b);
+int strncmp(const char *__a, const char *__b, size_t __n);
+char *strchr(const char *__s, int __c);
+char *strrchr(const char *__s, int __c);
+char *strstr(const char *__haystack, const char *__needle);
+char *strtok(char *__s, const char *__delim);
+char *strpbrk(const char *__s1, const char *__s2);
+size_t strspn(const char *__s1, const char *__s2);
+size_t strcspn(const char *__s1, const char *__s2);
+
+void *memset(void *__to, int __ch, unsigned int __n);
+int memcmp(const void *s1v, const void *s2v, int size);
+
+/* FIXME These are defined here only by tradition... we should move them. */
+void *memcpy(void *__to, const void *__from, unsigned int __n);
+void *memmove(void *__to, const void *__from, unsigned int __n);
+
+/*** BSD compatibility functions; do not use in new code ***/
+
+char *index(const char *__s, int __c);
+char *rindex(const char *__s, int __c);
+
+void bcopy(const void *__from, void *__to, unsigned int __n);
+void bzero(void *__to, unsigned int __n);
+
+#endif /* _FLUX_MC_STRING_H_ */
diff --git a/410user/libstring/strlen.c b/410user/libstring/strlen.c
new file mode 100644
index 0000000..089b028
--- /dev/null
+++ b/410user/libstring/strlen.c
@@ -0,0 +1,45 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: limach/strlen.c
+ * Author: Robert V. Baron at Carnegie Mellon
+ * Date: Oct 13, 1992
+ * Abstract:
+ * strlen returns the number of characters in "string" preceeding
+ * the terminating null character.
+ */
+
+int
+strlen(string)
+ register char *string;
+{
+register char *ret = string;
+
+ while (*string++);
+
+ return string - 1 - ret;
+
+}
diff --git a/410user/libstring/strncat.c b/410user/libstring/strncat.c
new file mode 100644
index 0000000..480b3b5
--- /dev/null
+++ b/410user/libstring/strncat.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <types.h>
+#include <string.h>
+
+/*
+ * Concatenate src on the end of dst. At most strlen(dst)+n+1 bytes
+ * are written at dst (at most n+1 bytes being appended). Return dst.
+ */
+char *
+strncat(dst, src, n)
+ char *dst;
+ const char *src;
+ register size_t n;
+{
+ if (n != 0) {
+ register char *d = dst;
+ register const char *s = src;
+
+ while (*d != 0)
+ d++;
+ do {
+ if ((*d = *s++) == 0)
+ break;
+ d++;
+ } while (--n != 0);
+ *d = 0;
+ }
+ return (dst);
+}
diff --git a/410user/libstring/strncmp.c b/410user/libstring/strncmp.c
new file mode 100644
index 0000000..6ce3f30
--- /dev/null
+++ b/410user/libstring/strncmp.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <string.h>
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+ while (1)
+ {
+ if (n <= 0)
+ return 0;
+ if (*s1 != *s2)
+ return *s1 - *s2;
+ if (*s1 == 0)
+ return 0;
+
+ s1++;
+ s2++;
+ n--;
+ }
+}
+
diff --git a/410user/libstring/strncpy.c b/410user/libstring/strncpy.c
new file mode 100644
index 0000000..19cf89a
--- /dev/null
+++ b/410user/libstring/strncpy.c
@@ -0,0 +1,51 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: libmach_sa/strncpy.c
+ * Author: Mary R. Thompson at Carnegie Mellon
+ * Date: Oct 13, 1992
+ * Abstract:
+ * strncpy copies "count" characters from the "from" string to
+ * the "to" string. If "from" contains less than "count" characters
+ * "to" will be padded with null characters until exactly "count"
+ * characters have been written. The return value is a pointer
+ * to the "to" string.
+ */
+
+char *
+strncpy(to, from, count)
+ register char *to, *from;
+ register int count;
+{
+ register char *ret = to;
+
+ while (count-- > 0 && (*to++ = *from++));
+
+ while (count-- > 0)
+ *to++ = '\0';
+
+ return ret;
+}
diff --git a/410user/libstring/strpbrk.c b/410user/libstring/strpbrk.c
new file mode 100644
index 0000000..12ddef9
--- /dev/null
+++ b/410user/libstring/strpbrk.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <types.h>
+#include <stddef.h>
+#include <string.h>
+
+/*
+ * Find the first occurrence in s1 of a character in s2 (excluding NUL).
+ */
+char *
+strpbrk(s1, s2)
+ register const char *s1, *s2;
+{
+ register const char *scanp;
+ register int c, sc;
+
+ while ((c = *s1++) != 0) {
+ for (scanp = s2; (sc = *scanp++) != 0;)
+ if (sc == c)
+ return ((char *)(s1 - 1));
+ }
+ return (NULL);
+}
diff --git a/410user/libstring/strrchr.c b/410user/libstring/strrchr.c
new file mode 100644
index 0000000..e7b5792
--- /dev/null
+++ b/410user/libstring/strrchr.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1996 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <string.h>
+#include <stddef.h>
+
+char *
+strrchr(const char *s, int c)
+{
+ char *save;
+
+ for (save = NULL; *s != '\0'; s++)
+ if (*s == c)
+ save = (char *)s;
+
+ return save;
+}
diff --git a/410user/libstring/strspn.c b/410user/libstring/strspn.c
new file mode 100644
index 0000000..a493f8f
--- /dev/null
+++ b/410user/libstring/strspn.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <types.h>
+#include <string.h>
+
+/*
+ * Span the string s2 (skip characters that are in s2).
+ */
+size_t
+strspn(s1, s2)
+ const char *s1;
+ register const char *s2;
+{
+ register const char *p = s1, *spanp;
+ register char c, sc;
+
+ /*
+ * Skip any characters in s2, excluding the terminating \0.
+ */
+cont:
+ c = *p++;
+ for (spanp = s2; (sc = *spanp++) != 0;)
+ if (sc == c)
+ goto cont;
+ return (p - 1 - s1);
+}
diff --git a/410user/libstring/strstr.c b/410user/libstring/strstr.c
new file mode 100644
index 0000000..7c2fb55
--- /dev/null
+++ b/410user/libstring/strstr.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+char *strstr(const char *haystack, const char *needle)
+{
+ int hlen = strlen(haystack);
+ int nlen = strlen(needle);
+
+ while (hlen >= nlen)
+ {
+ if (!memcmp(haystack, needle, nlen))
+ return (void*)haystack;
+
+ haystack++;
+ hlen--;
+ }
+ return 0;
+}
+
diff --git a/410user/libstring/strtok.c b/410user/libstring/strtok.c
new file mode 100644
index 0000000..ba4f85d
--- /dev/null
+++ b/410user/libstring/strtok.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stddef.h>
+
+char *
+strtok(s, delim)
+ register char *s;
+ register const char *delim;
+{
+ register char *spanp;
+ register int c, sc;
+ char *tok;
+ static char *last;
+
+
+ if (s == NULL && (s = last) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0) { /* no non-delimiter characters */
+ last = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ last = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/410user/libstring/user.mk b/410user/libstring/user.mk
new file mode 100644
index 0000000..60f0a39
--- /dev/null
+++ b/410user/libstring/user.mk
@@ -0,0 +1,27 @@
+410ULIB_STRING_OBJS:= \
+ memcmp.o \
+ memset.o \
+ rindex.o \
+ strcat.o \
+ strchr.o \
+ strcmp.o \
+ strcpy.o \
+ strcspn.o \
+ strdup.o \
+ strlen.o \
+ strncat.o \
+ strncmp.o \
+ strncpy.o \
+ strpbrk.o \
+ strrchr.o \
+ strspn.o \
+ strstr.o \
+ strtok.o \
+
+
+410ULIB_STRING_OBJS:= $(410ULIB_STRING_OBJS:%=$(410UDIR)/libstring/%)
+
+ALL_410UOBJS += $(410ULIB_STRING_OBJS)
+410UCLEANS += $(410UDIR)/libstring.a
+
+$(410UDIR)/libstring.a: $(410ULIB_STRING_OBJS)
diff --git a/410user/libtest/report.c b/410user/libtest/report.c
new file mode 100644
index 0000000..96d29a3
--- /dev/null
+++ b/410user/libtest/report.c
@@ -0,0 +1,98 @@
+/** @file 410user/libtest/report.c
+ * @brief Test reporting implementation
+ * @author elly1 U2009
+ */
+
+#include <stdio.h> /* snprintf */
+#include <stdlib.h> /* exit */
+#include <report.h>
+
+#include "410_tests.h" /* TEST_START_*, TEST_END_*, TEST_PFX */
+
+/* This is a GNUism used for the sake of maintainability. This way nothing
+ * horrible will happen if someone reorders the START_* constants in the header
+ * file. */
+const char *start_msgs[] = {
+ [START_CMPLT] = TEST_START_CMPLT,
+ [START_ABORT] = TEST_START_ABORT,
+ [START_4EVER] = TEST_START_4EVER,
+};
+
+const char *end_msgs[] = {
+ [END_SUCCESS] = TEST_END_SUCCESS,
+ [END_FAIL] = TEST_END_FAIL,
+};
+
+void format_start(char *buf, int len, int type) {
+ snprintf(buf, len, "%s%s%s", TEST_PFX, test_name, start_msgs[type]);
+}
+
+void format_end(char *buf, int len, int type) {
+ snprintf(buf, len, "%s%s%s", TEST_PFX, test_name, end_msgs[type]);
+}
+
+void format_misc(char *buf, int len, const char *msg) {
+ snprintf(buf, len, "%s%s%s", TEST_PFX, test_name, msg);
+}
+
+void format_err(char *buf, int len, const char *msg, int code) {
+ snprintf(buf, len, "%s%s%s%d", TEST_PFX, test_name, msg, code);
+}
+
+void report_start(int type) {
+ char buf[256];
+ format_start(buf, sizeof(buf), type);
+ sim_puts(buf);
+}
+
+void report_end(int type) {
+ char buf[256];
+ format_end(buf, sizeof(buf), type);
+ sim_puts(buf);
+
+ int success = (type == END_SUCCESS) ? 1 : 0;
+ sim_update_scoreboard((char *)test_name, success);
+}
+
+void report_misc(const char *msg) {
+ char buf[256];
+ format_misc(buf, sizeof(buf), msg);
+ sim_puts(buf);
+}
+
+void report_fmt(const char *fmt, ...) {
+ va_list ap;
+ char b[256];
+ char buf[256];
+ va_start(ap, fmt);
+ vsnprintf(b, sizeof(b), fmt, ap);
+ va_end(ap);
+ snprintf(buf, sizeof(buf), "%s%s%s", TEST_PFX, test_name, b);
+ sim_puts(buf);
+}
+
+void report_err(const char *msg, int code) {
+ char buf[256];
+ format_err(buf, sizeof(buf), msg, code);
+ sim_puts(buf);
+}
+
+void report_fatal(const char *msg, int code) {
+ report_err(msg, code);
+ report_end(END_FAIL);
+}
+
+void report_on_err(const char *exp, int line, int v) {
+ char buf[256];
+ if (v >= 0) { return; }
+ snprintf(buf, sizeof(buf), "%s%sErr %d on line %d: `%s'",
+ TEST_PFX, test_name, v, line, exp);
+ sim_puts(buf);
+}
+
+void fatal_on_err(const char *exp, int line, int v) {
+ report_on_err(exp, line, v);
+ if (v >= 0) { return; }
+ report_end(END_FAIL);
+ exit(v);
+}
diff --git a/410user/libtest/report.h b/410user/libtest/report.h
new file mode 100644
index 0000000..496754b
--- /dev/null
+++ b/410user/libtest/report.h
@@ -0,0 +1,109 @@
+/** @file 410user/libtest/report.h
+ * @brief Test reporting interface
+ * @author elly1 U2009
+ */
+
+#ifndef LIBTEST_REPORT_H
+#define LIBTEST_REPORT_H
+
+extern const char* test_name; /* Defined by the test in question with
+ * DEF_TEST_NAME() */
+
+enum {
+ START_CMPLT = 0,
+ START_ABORT = 1,
+ START_4EVER = 2,
+};
+
+/** @brief Formats a test start message into a buffer.
+ * @param buf Buffer to format into.
+ * @param len Length of the buffer.
+ * @param type Type of test start.
+ * @return Void.
+ */
+extern void format_start(char *buf, int len, int type);
+
+/** @brief Reports the start of a test.
+ * @param type Type of test start.
+ */
+extern void report_start(int type);
+
+enum {
+ END_SUCCESS = 0,
+ END_FAIL = 1,
+};
+
+/** @brief Formats a test end message into a buffer.
+ * @param buf Buffer to format into.
+ * @param len Length of the buffer.
+ * @param type Type of test ending.
+ * @return Void.
+ */
+extern void format_end(char *buf, int len, int type);
+
+/** @brief Reports the end of a test.
+ * @param type Type of test end.
+ */
+extern void report_end(int type);
+
+/** @brief Formats a miscellaneous message into a buffer.
+ * @param buf Buffer to format into.
+ * @param len Length of the buffer.
+ * @param msg Message to format.
+ * @return Void.
+ */
+extern void format_misc(char *buf, int len, const char *msg);
+
+/** @brief Report a miscellaneous happenstance.
+ * @param msg Happenstance.
+ * @return Void.
+ */
+extern void report_misc(const char *msg);
+
+/** @brief Report an arbitrary formatted message.
+ * @param fmt Format.
+ * @param ... Varargs.
+ * @return Void.
+ */
+extern void report_fmt(const char *fmt, ...);
+
+/** @brief Formats an error message into a buffer.
+ * @param buf Buffer to format into.
+ * @param len Length of the buffer.
+ * @param msg Message to format.
+ * @param code Error code.
+ * @return Void.
+ */
+extern void format_err(char *buf, int len, const char *msg, int code);
+
+/** @brief Report an error.
+ * @param msg Error message.
+ * @param code Error code.
+ * @return Void.
+ */
+extern void report_err(const char *msg, int code);
+
+/** @brief Report an error, and fail out.
+ * @param msg Error message.
+ * @param code Error code.
+ * @return Void.
+ */
+extern void report_fatal(const char *msg, int code);
+
+/** @brief Require that an expression succeed.
+ * @param exp Expression, as a string.
+ * @param line Line number of the expression.
+ * @param v Expression value.
+ * @return Void.
+ */
+extern void report_on_err(const char *exp, int line, int v);
+
+/** @brief Fail the test if an expression fails.
+ * @param exp Expression, as a string.
+ * @param line Line number of the expression.
+ * @param v Expression value.
+ * @return Void.
+ */
+extern void fatal_on_err(const char *exp, int line, int v);
+
+#endif /* !LIBTEST_REPORT_H */
diff --git a/410user/libtest/test.c b/410user/libtest/test.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/410user/libtest/test.c
diff --git a/410user/libtest/test.h b/410user/libtest/test.h
new file mode 100644
index 0000000..e47bfb5
--- /dev/null
+++ b/410user/libtest/test.h
@@ -0,0 +1,52 @@
+/** @file 410user/libtest/test.h
+ * @brief Test library.
+ * @author elly1 U2009
+ */
+
+#ifndef LIBTEST_TEST_H
+#define LIBTEST_TEST_H
+
+/** @brief Jump to 'func' with the system under low-memory conditions.
+ * The reason why this takes a function pointer may not be immediately clear.
+ * Once exhaustion() returns to C, the compiler is immediately free to save off
+ * all the registers and generally touch the stack; this could cause a failed
+ * stack page allocation and lead to the thread being killed, which would fail
+ * the test. As such, exhaustion guarantees that once you are out of memory, it
+ * will not touch the stack on your behalf.
+ *
+ * @param func Function to jump to.
+ * @param arg Argument passed to func in %ebx.
+ * @return Does not return.
+ */
+extern void exhaustion(void (*func)(void *), void *arg) __attribute__((noreturn));
+
+/** @brief Fork, and exit immediately, printing success regardless of what
+ * happened. Does not touch the stack at all.
+ * @param arg Argument passed in *in %ebx*.
+ * @return Does not return.
+ *
+ * NOTE:
+ * Do not call this function directly. It is designed to be passed into
+ * exhaustion().
+ */
+extern void fork_and_exit(void *arg) __attribute__((noreturn));
+
+/** @brief Exit immediately, with a success message.
+ * @param arg Argument passed in *in %ebx*.
+ * @return Does not return.
+ *
+ * See the note attached to fork_and_exit().
+ */
+extern void exit_success(void *arg) __attribute__((noreturn));
+
+/** @brief Execute an illegal instruction.
+ * @return Void.
+ */
+extern void illegal(void);
+
+/** @brief Assuredly invoke the misbehave() system call
+ * @return Void ("you are not expected to understand this")
+ */
+extern void assuredly_misbehave(int mode);
+
+#endif /* !LIBTEST_TEST_H */
diff --git a/410user/libtest/testasm.S b/410user/libtest/testasm.S
new file mode 100644
index 0000000..d0179ab
--- /dev/null
+++ b/410user/libtest/testasm.S
@@ -0,0 +1,82 @@
+/** @file 410user/libtest/testasm.S
+ * @brief Test library.
+ * @author elly1 U2009
+ */
+
+#include <simics.h>
+#include <syscall_int.h>
+
+.global exhaustion
+
+#define EX_BASE 0x20000000
+#define EX_SIZE 1024 * 1024 * 1024
+
+/* %edi - continuation
+ * %esi - syscall arg frame
+ * %ebx - argument
+ */
+exhaustion:
+ mov 4(%esp), %edi
+ mov 8(%esp), %ebx
+ lea -8(%esp), %esi /* argument frame space */
+ mov $EX_BASE, %ecx
+ mov $EX_SIZE, %edx
+ mov $4, %esp /* don't tempt the user to think that their stack is
+ * still live */
+loop:
+ cmp $4096, %edx
+ jb 1f
+ mov %ecx, (%esi)
+ mov %edx, 4(%esi)
+ int $NEW_PAGES_INT
+ test %eax, %eax
+ jnz smaller
+ add %edx, %ecx
+ jmp loop
+smaller:
+ shr $1, %edx
+ jmp loop
+1:
+ jmp *%edi
+
+.global fork_and_exit
+
+fork_and_exit:
+ mov %ebx, %ecx
+ int $FORK_INT
+ test %eax, %eax
+ jz 1f
+ INLINE_SIMCALL(SIM_PUTS, %ecx, $0)
+1:
+ mov $0, %esi
+ int $SET_STATUS_INT
+ int $VANISH_INT
+
+.global exit_success
+
+exit_success:
+ mov %ebx, %ecx
+ INLINE_SIMCALL(SIM_PUTS, %ecx, $0)
+ INLINE_SIMCALL(SIM_TEST_REPORT, %ecx, $1)
+ mov $0, %esi
+ int $SET_STATUS_INT
+ int $VANISH_INT
+
+.global illegal
+
+illegal:
+ xor %eax, %eax
+ mov %eax, %cr0
+ ret
+
+/* Don't code like this: "authorized personnel only". */
+.global assuredly_misbehave
+assuredly_misbehave:
+ pushl %ebp
+ movl %esp, %ebp
+ pusha
+ movl 8(%ebp), %esi
+ int $MISBEHAVE_INT
+ popa
+ leave
+ ret
diff --git a/410user/libtest/user.mk b/410user/libtest/user.mk
new file mode 100644
index 0000000..a302d02
--- /dev/null
+++ b/410user/libtest/user.mk
@@ -0,0 +1,6 @@
+410U_TEST_OBJS := test.o testasm.o report.o
+410U_TEST_OBJS := $(410U_TEST_OBJS:%=$(410UDIR)/libtest/%)
+ALL_410UOBJS += $(410U_TEST_OBJS)
+410UCLEANS += $(410UDIR)/libtest.a
+
+$(410UDIR)/libtest.a: $(410U_TEST_OBJS)
diff --git a/410user/libthrgrp/thrgrp.c b/410user/libthrgrp/thrgrp.c
new file mode 100644
index 0000000..ecd124a
--- /dev/null
+++ b/410user/libthrgrp/thrgrp.c
@@ -0,0 +1,201 @@
+/* @file thrgrp.c
+ * @brief This file contains the implementation of the wrapper for the
+ * thread library. This wrapper allows explicit control over what threads
+ * get joined on by what other threads.
+ *
+ * @author Matthew Brewer (mbrewer)
+ *
+ * The user allocates groups, and then initializes them.
+ * They can then spawn threads into these groups with thrgrp_create()
+ * When the threads exit (via returning.. NOT thr_exit()), they can be
+ * joined on using thrgrp_join(). A call to thrgrp_join() with group tg
+ * will reap any one thread to exit from that group, and then return.
+ */
+
+#include <cond.h>
+#include <thrgrp.h>
+#include <thread.h>
+#include <stddef.h>
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <simics.h>
+#include <assert.h>
+
+/**
+ * @brief Initializes a thread group
+ *
+ * This function basically just initializes mutexes etc.
+ *
+ * @param eg An unitialized, but allocated, thread group to be initialized
+ * @return 0 on success, nonzero otherwise
+ *
+ * @pre thr_init should have been called
+ * @post eg is initialized
+ */
+int thrgrp_init_group(thrgrp_group_t *eg) {
+ int ret;
+
+ eg->zombie_in = NULL;
+ eg->zombie_out = NULL;
+ if ((ret = mutex_init(&(eg->lock))))
+ return ret;
+ if ((ret = cond_init(&(eg->cv)))) {
+ mutex_destroy(&(eg->lock));
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * @brief Destroys an initialized thrgroup
+ *
+ * Destroys the mutexes and other related stuff
+ *
+ * @param eg An initialized thread group to be destroyed
+ * @return 0 on success, nonzero otherwise
+ *
+ * @pre thrgrp_init_group(eg) has been called
+ * @post eg is uninitialized (but still allocated)
+ */
+int thrgrp_destroy_group(thrgrp_group_t *eg) {
+ int ret = 0;
+
+ mutex_lock(&(eg->lock));
+
+ /* make sure that the queues are empty */
+ if (eg->zombie_in || eg->zombie_out)
+ ret = 1;
+
+ mutex_unlock(&(eg->lock));
+
+ if (ret == 0) {
+ mutex_destroy(&(eg->lock));
+ cond_destroy(&(eg->cv));
+ }
+ return ret;
+}
+
+/**
+ * @brief Function to sit on the bottom of the thread stack
+ *
+ * @param in_data is a thrgrp_data_t, with tmp loaded with the function
+ * the user wants to run, the argument to call the function on, and
+ * the thread group this new thread is to be spawned in
+ * @return doesn't
+ */
+static void *thrgrp_bottom(void *in_data) {
+ thrgrp_data_t *data = (thrgrp_data_t *)in_data;
+ void *(*func)(void *) = data->tmp.func;
+ void *arg = data->tmp.arg;
+ thrgrp_group_t *tg = data->tmp.tg;
+ void *ret;
+
+ /* now that we have all of the data out of data,
+ we'll use it as our queueing element */
+ data->qel.next = NULL;
+ data->qel.tid = thr_getid();
+
+ /* run the code we were asked to run */
+ ret = func(arg);
+
+ /* insert ourselves into the zombie queue */
+ mutex_lock(&(tg->lock));
+ if (tg->zombie_in)
+ tg->zombie_in->next = &(data->qel);
+ tg->zombie_in = &(data->qel);
+ if (tg->zombie_out == NULL)
+ tg->zombie_out = &(data->qel);
+
+ /* signal a waiter to come clean up our zombie */
+ cond_signal(&(tg->cv));
+ mutex_unlock(&(tg->lock));
+
+ /* if we return with ret, should exit with ret */
+ return ret;
+}
+
+/** @brief spawns a new thread in the thread group
+ *
+ * @param tg, an initialized thread group to spawn the new thread in
+ * @param func, function to run in the new thread
+ * @param arg, argument to pass the function to func
+ * @return 0 on success, nonzero otherwise
+ */
+int thrgrp_create(thrgrp_group_t *tg, void *(*func)(void *), void *arg) {
+ int tid;
+ thrgrp_data_t *data;
+
+ /* setup a hunk of data
+ this is used both to get the arguments into the other thread,
+ and then as the memory to go on the zombie queue, this way we
+ malloc only once */
+ data = malloc(sizeof(thrgrp_data_t));
+ if (data == NULL)
+ return -1;
+ data->tmp.func = func;
+ data->tmp.arg = arg;
+ data->tmp.tg = tg;
+
+ /* spawn the thread */
+ tid = thr_create(thrgrp_bottom, data);
+
+ /* tid < 0 indicates error */
+ if (tid < 0) {
+ free(data);
+ return tid;
+ }
+
+ /* we don't return the tid, because you're not supposed to join on it
+ must be joined with thrgrp_join(), not thr_join() */
+ return 0;
+}
+
+/** @brief joins on any thread in the group which exits
+ *
+ * like thr_join(), but will join on any exited thread which was spawned into
+ * this thread group via thrgrp_create()
+ *
+ * throughout this function thrgrp_queue_el_t is a LIE! in reality this is
+ * thrgrp_data_t, a union including thrgrp_queue_el_t as a subtype. this is
+ * only important because one should realize "free" is freeing thrgrp_data_t
+ * of memory, not thrgrp_queue_el_t of memory
+ *
+ * @param eg, an initialized thread group to join on threads in
+ * @param depared, a pointer to some memory, the TID of the exited
+ * thread will be placed here before thrgrp_join returns
+ * @param status, a pointer to a void *, where the return status of
+ * the thread we join on (i.e., what's returned from that thread's first function
+ * @return returns the result of thr_join
+ */
+int thrgrp_join(thrgrp_group_t *eg, void **status) {
+ thrgrp_queue_el_t *thr_data;
+ int tid;
+
+ mutex_lock(&(eg->lock));
+ /* check to see if there's someone to join on */
+ while (eg->zombie_out == NULL) {
+ /* wait until there is someone to join on */
+ cond_wait(&(eg->cv), &(eg->lock));
+ /* inside of cond_wait, someone can sneek in
+ * i.e., even if condition variables are implemented in-order
+ * we do not have guaranteed in-order joins */
+ }
+
+ /* get our zombie from the queue */
+ thr_data = eg->zombie_out;
+ if (eg->zombie_out == eg->zombie_in) {
+ eg->zombie_in = NULL;
+ eg->zombie_out = NULL;
+ } else {
+ eg->zombie_out = eg->zombie_out->next;
+ }
+ mutex_unlock(&(eg->lock));
+
+ /* grab the tid out before we free it */
+ tid = thr_data->tid;
+ /* free the memory from the queue */
+ free(thr_data);
+ /* join on the tid, and return the result */
+ return thr_join(tid, status);
+}
diff --git a/410user/libthrgrp/thrgrp.h b/410user/libthrgrp/thrgrp.h
new file mode 100644
index 0000000..73e9e2d
--- /dev/null
+++ b/410user/libthrgrp/thrgrp.h
@@ -0,0 +1,71 @@
+/* @file thrgrp.h
+ * @brief This file defines the interface for the thread library wrapper.
+ * This wrapper allows explicit control over what exiting threads get joined
+ * on by what joining threads.
+ * @author Matthew Brewer (mbrewer)
+ */
+
+#ifndef THRGRP_H
+#define THRGRP_H
+#include <cond.h>
+
+/**
+ * @brief This is an element of a thread group queue, used for storing
+ * exited threads.
+ */
+typedef struct thrgrp_queue_el {
+ /** @brief the next element in the queue */
+ struct thrgrp_queue_el *next;
+ /** @brief the tid of the thread to exit */
+ int tid;
+} thrgrp_queue_el_t;
+
+/**
+ * @brief This is a structure holding information for joining and exiting
+ * threads. The idea is that threads exiting on this exitgroup can be joined
+ * on by threads joining on this exitgroup.
+ */
+typedef struct {
+ /* @brief a condition variable holding joiners waiting on exiters */
+ cond_t cv;
+ /* @brief a list of zombie threads waiting to be reaped */
+ thrgrp_queue_el_t *zombie_in;
+ thrgrp_queue_el_t *zombie_out;
+ /* @brief a mutex for protecting the rest of this data */
+ mutex_t lock;
+} thrgrp_group_t;
+
+/**
+ * @brief This is a temporary structure used for passing data into a spawned
+ * thread
+ */
+typedef struct thrgrp_tmp_data {
+ /** @brief function to call in newly spaned thread */
+ void *(*func)(void *);
+ /** @brief argument to func */
+ void *arg;
+ /** @brief thread group to spawn the new thread in */
+ thrgrp_group_t *tg;
+} thrgrp_tmp_data_t;
+
+/**
+ * @brief This is a union for malloc purposes, so it can be used for
+ * either a queue element, or temporary data, this way we only have to
+ * malloc once per thread spawn
+ */
+typedef union thrgrp_data {
+ /** @brief a queue element */
+ thrgrp_queue_el_t qel;
+ /** @brief a temporary data structure */
+ thrgrp_tmp_data_t tmp;
+} thrgrp_data_t;
+
+int thrgrp_init_group(thrgrp_group_t *eg);
+
+int thrgrp_destroy_group(thrgrp_group_t *eg);
+
+int thrgrp_create(thrgrp_group_t *tg, void *(*func)(void *), void *args);
+
+int thrgrp_join(thrgrp_group_t *tg, void **status);
+
+#endif /* WRAPTH_H */
diff --git a/410user/libthrgrp/user.mk b/410user/libthrgrp/user.mk
new file mode 100644
index 0000000..b35ea3a
--- /dev/null
+++ b/410user/libthrgrp/user.mk
@@ -0,0 +1,7 @@
+410ULIB_THRGRP_OBJS := thrgrp.o
+410ULIB_THRGRP_OBJS := $(410ULIB_THRGRP_OBJS:%=$(410UDIR)/libthrgrp/%)
+
+ALL_410UOBJS += $(410ULIB_THRGRP_OBJS)
+410UCLEANS += $(410UDIR)/libthrgrp.a
+
+$(410UDIR)/libthrgrp.a: $(410ULIB_THRGRP_OBJS)
diff --git a/410user/libx86/bcopy.S b/410user/libx86/bcopy.S
new file mode 100644
index 0000000..f687231
--- /dev/null
+++ b/410user/libx86/bcopy.S
@@ -0,0 +1,135 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <asm_style.h>
+
+
+#if 0 /* is this useful? */
+
+/* l2rbcopy(from, to, bcount) */
+
+ENTRY(l2rbcopy)
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %edi
+ pushl %esi
+ movl B_ARG2,%edx
+ movl B_ARG1,%edi
+ movl B_ARG0,%esi
+/* move longs */
+0: cld
+ movl %edx,%ecx
+ sarl $2,%ecx
+ js 1f
+ rep
+ movsl
+/* move bytes */
+ movl %edx,%ecx
+ andl $3,%ecx
+ rep
+ movsb
+1:
+ popl %esi
+ popl %edi
+ leave
+ ret
+#endif
+
+
+
+/*
+ * bcopy - like l2rbcopy, but recognizes overlapping ranges and handles
+ * them correctly.
+ * bcopy(from, to, bytes)
+ * char *from, *to;
+ * int bytes;
+ */
+ENTRY(bcopy)
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %edi
+ pushl %esi
+ movl B_ARG0,%esi
+ movl B_ARG1,%edi
+bcopy_common:
+ movl B_ARG2,%edx
+ leal (%esi,%edx), %eax /* from + bytes */
+ cmpl %eax, %edi /* <= to */
+ jae 0f
+ leal (%edi,%edx), %eax /* to + bytes */
+ cmpl %eax, %esi /* <= from */
+ jae 0f
+ cmpl %esi, %edi /* from > to */
+ jb 0f
+ je 1f
+
+ addl %edx, %esi; decl %esi
+ addl %edx, %edi; decl %edi
+ std
+ movl %edx,%ecx
+/* move bytes backwards */
+ rep
+ movsb
+ cld
+1:
+/* memcpy: return dest pointer */
+ movl B_ARG0,%eax
+ popl %esi
+ popl %edi
+ leave
+ ret
+/* move words forwards */
+0: cld
+ movl %edx,%ecx
+ sarl $2,%ecx
+ js 2f
+ rep
+ movsl
+/* move bytes forwards */
+ movl %edx,%ecx
+ andl $3,%ecx
+ rep
+ movsb
+2:
+/* memcpy: return dest pointer */
+ movl B_ARG0,%eax
+ popl %esi
+ popl %edi
+ leave
+ ret
+
+/* memcpy(to, from, count) */
+
+ENTRY(memcpy)
+ENTRY(memmove)
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %edi
+ pushl %esi
+ movl B_ARG0,%edi
+ movl B_ARG1,%esi
+ jmp bcopy_common
+
diff --git a/410user/libx86/bzero.S b/410user/libx86/bzero.S
new file mode 100644
index 0000000..6675745
--- /dev/null
+++ b/410user/libx86/bzero.S
@@ -0,0 +1,47 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <asm_style.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: bzero.S,v 1.8 1995/04/28 22:57:58 jtc Exp $")
+#endif
+
+
+ENTRY(bzero)
+ pushl %edi
+ movl S_ARG1,%edi
+ movl S_ARG2,%edx
+
+ cld /* set fill direction forward */
+ xorl %eax,%eax /* set fill data to 0 */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpl $16,%edx
+ jb L1
+
+ movl %edi,%ecx /* compute misalignment */
+ negl %ecx
+ andl $3,%ecx
+ subl %ecx,%edx
+ rep /* zero until word aligned */
+ stosb
+
+ movl %edx,%ecx /* zero by words */
+ shrl $2,%ecx
+ andl $3,%edx
+ rep
+ stosl
+
+L1: movl %edx,%ecx /* zero remainder by bytes */
+ rep
+ stosb
+
+ popl %edi
+ ret
diff --git a/410user/libx86/gccisms.c b/410user/libx86/gccisms.c
new file mode 100644
index 0000000..fea7c5b
--- /dev/null
+++ b/410user/libx86/gccisms.c
@@ -0,0 +1,346 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ------------
+ *
+ * Lovingly ripped, slashed, mangled, and mutilated into one file by nwf@,
+ * 20080814 to fit inside the CS410 universe; in some places this has resulted
+ * in very carefully constructed, portable code becoming x86 specific. Sorry.
+ *
+ * Taken from ftp://ftp.openbsd.org/pub/OpenBSD/3.9/sys.tar.gz
+ */
+
+#define HALF_BITS (sizeof(int)*8/2)
+#define B ((int)1 << HALF_BITS) /* digit base */
+#define H 1 /* Endianness matters */
+#define L 0
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_int/2)). (`x' must actually be u_int.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(int)*CHAR_BIT/2).
+ */
+#define HHALF(x) ((u_int)(x) >> HALF_BITS)
+#define LHALF(x) ((u_int)(x) & (((int)1 << HALF_BITS) - 1))
+
+typedef unsigned int u_int;
+
+typedef u_int digit;
+typedef long long quad_t; /* 64 bits, signed */
+typedef unsigned long long u_quad_t; /* 64 bits, unsigned */
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+ quad_t q; /* as a (signed) quad */
+ u_quad_t uq; /* as an unsigned quad */
+ int sl[2]; /* as two signed ints */
+ u_int ul[2]; /* as two unsigned ints */
+};
+
+/* Combine two `digits' to make a single two-digit number. */
+#define COMBINE(a, b) (((u_int)(a) << HALF_BITS) | (b))
+
+
+static void shl(digit *p, int len, int sh);
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_int. As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+ union uu tmp;
+ digit *u, *v, *q;
+ digit v1, v2;
+ u_int qhat, rhat, t;
+ int m, n, d, j, i;
+ digit uspace[5], vspace[5], qspace[5];
+
+ /*
+ * Take care of special cases: divide by zero, and u < v.
+ */
+ if (vq == 0) {
+ /* divide by zero. */
+ static volatile const unsigned int zero = 0;
+
+ tmp.ul[H] = tmp.ul[L] = 1 / zero;
+ if (arq)
+ *arq = uq;
+ return (tmp.q);
+ }
+ if (uq < vq) {
+ if (arq)
+ *arq = uq;
+ return (0);
+ }
+ u = &uspace[0];
+ v = &vspace[0];
+ q = &qspace[0];
+
+ /*
+ * Break dividend and divisor into digits in base B, then
+ * count leading zeros to determine m and n. When done, we
+ * will have:
+ * u = (u[1]u[2]...u[m+n]) sub B
+ * v = (v[1]v[2]...v[n]) sub B
+ * v[1] != 0
+ * 1 < n <= 4 (if n = 1, we use a different division algorithm)
+ * m >= 0 (otherwise u < v, which we already checked)
+ * m + n = 4
+ * and thus
+ * m = 4 - n <= 2
+ */
+ tmp.uq = uq;
+ u[0] = 0;
+ u[1] = (digit)HHALF(tmp.ul[H]);
+ u[2] = (digit)LHALF(tmp.ul[H]);
+ u[3] = (digit)HHALF(tmp.ul[L]);
+ u[4] = (digit)LHALF(tmp.ul[L]);
+ tmp.uq = vq;
+ v[1] = (digit)HHALF(tmp.ul[H]);
+ v[2] = (digit)LHALF(tmp.ul[H]);
+ v[3] = (digit)HHALF(tmp.ul[L]);
+ v[4] = (digit)LHALF(tmp.ul[L]);
+ for (n = 4; v[1] == 0; v++) {
+ if (--n == 1) {
+ u_int rbj; /* r*B+u[j] (not root boy jim) */
+ digit q1, q2, q3, q4;
+
+ /*
+ * Change of plan, per exercise 16.
+ * r = 0;
+ * for j = 1..4:
+ * q[j] = floor((r*B + u[j]) / v),
+ * r = (r*B + u[j]) % v;
+ * We unroll this completely here.
+ */
+ t = v[2]; /* nonzero, by definition */
+ q1 = (digit)(u[1] / t);
+ rbj = COMBINE(u[1] % t, u[2]);
+ q2 = (digit)(rbj / t);
+ rbj = COMBINE(rbj % t, u[3]);
+ q3 = (digit)(rbj / t);
+ rbj = COMBINE(rbj % t, u[4]);
+ q4 = (digit)(rbj / t);
+ if (arq)
+ *arq = rbj % t;
+ tmp.ul[H] = COMBINE(q1, q2);
+ tmp.ul[L] = COMBINE(q3, q4);
+ return (tmp.q);
+ }
+ }
+
+ /*
+ * By adjusting q once we determine m, we can guarantee that
+ * there is a complete four-digit quotient at &qspace[1] when
+ * we finally stop.
+ */
+ for (m = 4 - n; u[1] == 0; u++)
+ m--;
+ for (i = 4 - m; --i >= 0;)
+ q[i] = 0;
+ q += 4 - m;
+
+ /*
+ * Here we run Program D, translated from MIX to C and acquiring
+ * a few minor changes.
+ *
+ * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+ */
+ d = 0;
+ for (t = v[1]; t < B / 2; t <<= 1)
+ d++;
+ if (d > 0) {
+ shl(&u[0], m + n, d); /* u <<= d */
+ shl(&v[1], n - 1, d); /* v <<= d */
+ }
+ /*
+ * D2: j = 0.
+ */
+ j = 0;
+ v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
+ v2 = v[2]; /* for D3 */
+ do {
+ digit uj0, uj1, uj2;
+
+ /*
+ * D3: Calculate qhat (\^q, in TeX notation).
+ * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+ * let rhat = (u[j]*B + u[j+1]) mod v[1].
+ * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+ * decrement qhat and increase rhat correspondingly.
+ * Note that if rhat >= B, v[2]*qhat < rhat*B.
+ */
+ uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+ uj1 = u[j + 1]; /* for D3 only */
+ uj2 = u[j + 2]; /* for D3 only */
+ if (uj0 == v1) {
+ qhat = B;
+ rhat = uj1;
+ goto qhat_too_big;
+ } else {
+ u_int nn = COMBINE(uj0, uj1);
+ qhat = nn / v1;
+ rhat = nn % v1;
+ }
+ while (v2 * qhat > COMBINE(rhat, uj2)) {
+ qhat_too_big:
+ qhat--;
+ if ((rhat += v1) >= B)
+ break;
+ }
+ /*
+ * D4: Multiply and subtract.
+ * The variable `t' holds any borrows across the loop.
+ * We split this up so that we do not require v[0] = 0,
+ * and to eliminate a final special case.
+ */
+ for (t = 0, i = n; i > 0; i--) {
+ t = u[i + j] - v[i] * qhat - t;
+ u[i + j] = (digit)LHALF(t);
+ t = (B - HHALF(t)) & (B - 1);
+ }
+ t = u[j] - t;
+ u[j] = (digit)LHALF(t);
+ /*
+ * D5: test remainder.
+ * There is a borrow if and only if HHALF(t) is nonzero;
+ * in that (rare) case, qhat was too large (by exactly 1).
+ * Fix it by adding v[1..n] to u[j..j+n].
+ */
+ if (HHALF(t)) {
+ qhat--;
+ for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+ t += u[i + j] + v[i];
+ u[i + j] = (digit)LHALF(t);
+ t = HHALF(t);
+ }
+ u[j] = (digit)LHALF(u[j] + t);
+ }
+ q[j] = (digit)qhat;
+ } while (++j <= m); /* D7: loop on j. */
+
+ /*
+ * If caller wants the remainder, we have to calculate it as
+ * u[m..m+n] >> d (this is at most n digits and thus fits in
+ * u[m+1..m+n], but we may need more source digits).
+ */
+ if (arq) {
+ if (d) {
+ for (i = m + n; i > m; --i)
+ u[i] = (digit)(((u_int)u[i] >> d) |
+ LHALF((u_int)u[i - 1] << (HALF_BITS - d)));
+ u[i] = 0;
+ }
+ tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+ tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+ *arq = tmp.q;
+ }
+
+ tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+ tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+ return (tmp.q);
+}
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ p[i] = (digit)(LHALF((u_int)p[i] << sh) |
+ ((u_int)p[i + 1] >> (HALF_BITS - sh)));
+ p[i] = (digit)(LHALF((u_int)p[i] << sh));
+}
+
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(u_quad_t a, u_quad_t b)
+{
+ u_quad_t r;
+
+ (void)__qdivrem(a, b, &r);
+ return (r);
+}
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(u_quad_t a, u_quad_t b)
+{
+
+ return (__qdivrem(a, b, (u_quad_t *)0));
+}
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+ u_quad_t ua, ub, uq;
+ int neg = 0;
+
+ ua = a;
+ ub = b;
+
+ if (a < 0)
+ ua = -ua, neg ^= 1;
+ if (b < 0)
+ ub = -ub, neg ^= 1;
+
+ uq = __qdivrem(ua, ub, (u_quad_t *)0);
+ if (neg)
+ uq = - uq;
+ return uq;
+}
diff --git a/410user/libx86/user.mk b/410user/libx86/user.mk
new file mode 100644
index 0000000..a583822
--- /dev/null
+++ b/410user/libx86/user.mk
@@ -0,0 +1,11 @@
+410U_X86_OBJS := \
+ bcopy.o \
+ bzero.o \
+ gccisms.o \
+
+410U_X86_OBJS := $(410U_X86_OBJS:%=$(410UDIR)/libx86/%)
+
+ALL_410UOBJS += $(410U_X86_OBJS)
+410UCLEANS += $(410UDIR)/libx86.a
+
+$(410UDIR)/libx86.a: $(410U_X86_OBJS)
diff --git a/410user/progs/ack.c b/410user/progs/ack.c
new file mode 100644
index 0000000..2375ad9
--- /dev/null
+++ b/410user/progs/ack.c
@@ -0,0 +1,56 @@
+/** @file 410user/progs/ack.c
+ * @author acrichto
+ * @brief Computes Ackermann function in multiple threads
+ * @public yes
+ * @for p4-smp
+ * @status done
+ */
+
+/* "Because not all total computable functions are primitive recursive" */
+
+#include <thread.h>
+#include <thrgrp.h>
+#include <410_tests.h>
+#include <stdio.h>
+#include <syscall.h>
+
+DEF_TEST_NAME("ack:");
+
+#define ACKN 8
+#define THREADS 8
+
+typedef void*(thr_func)(void*);
+
+int ack(int m, int n) {
+ if (m == 0) return n + 1;
+ if (n == 0) return ack(m - 1, 1);
+ return ack(m - 1, ack(m, n - 1));
+}
+
+void* ackstart(void *n) {
+ return (void*) ack(3, (int) n);
+}
+
+int main() {
+ thr_init(1024 * 128);
+ int ticks = get_ticks();
+ int i, answer, guess;
+ thrgrp_group_t group;
+
+ REPORT_ON_ERR(thrgrp_init_group(&group));
+ for (i = 0; i < THREADS; i++) {
+ REPORT_ON_ERR(thrgrp_create(&group, (thr_func*) ackstart, (void*) ACKN));
+ }
+
+ REPORT_ON_ERR(thrgrp_join(&group, (void*) &answer));
+ for (i = 1; i < THREADS; i++) {
+ REPORT_ON_ERR(thrgrp_join(&group, (void*) &guess));
+ if (guess != answer) {
+ REPORT_END_FAIL;
+ }
+ }
+ printf("ack(3, %d) = %d\n", ACKN, answer);
+ printf("ticks taken: %d\n", get_ticks() - ticks);
+
+ thr_exit(0);
+}
diff --git a/410user/progs/actual_wait.c b/410user/progs/actual_wait.c
new file mode 100644
index 0000000..983ddb2
--- /dev/null
+++ b/410user/progs/actual_wait.c
@@ -0,0 +1,131 @@
+/** @file 410user/progs/actual_wait.c
+ * @author de0u
+ * @brief Exercises wait() and vanish().
+ * @public yes
+ * @for p2 p3
+ * @covers wait vanish fork yield set_status
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <simics.h>
+
+#include "410_tests.h"
+DEF_TEST_NAME("actual_wait:");
+
+#define NCHILD 40 /* must be < 255 */
+#define PRESERVE (1024*1024)
+
+void child(int);
+
+int main(void)
+{
+ char buf[4096];
+ int pid, pids[NCHILD];
+ int c, preserve;
+ char msg[128];
+
+ buf[0] = buf[sizeof (buf) - 1] = 'q';
+
+ REPORT_START_CMPLT;
+
+ for (c = 0; c < NCHILD; ++c)
+ switch(((pid = fork()) < 0) ? -1 : pid) {
+ case -1:
+ REPORT_MISC("cannot fork");
+ goto fail;
+ case 0:
+ child(c);
+ break;
+ default:
+ pids[c] = pid;
+
+ snprintf(msg, sizeof (msg), "slot %d pid %d", c, pid);
+ printf("%s\n", msg);
+ REPORT_MISC(msg);
+
+ if (c & 1)
+ yield(-1);
+ break;
+ }
+
+ for (c = 0; c < NCHILD; ++c) {
+ int slot;
+ char msg[128];
+
+ if ((c & 8) == 8)
+ yield(-1);
+
+ pid = wait(&slot);
+
+ snprintf(msg, sizeof (msg), "slot %d pid %d", slot, pid);
+ printf("%s\n", msg);
+ REPORT_MISC(msg);
+
+ if ((slot < 0) || (slot >= NCHILD)) {
+ REPORT_MISC("invalid slot");
+ goto fail;
+ }
+ if (pids[slot] != pid) {
+ REPORT_MISC("pid/slot mismatch");
+ goto fail;
+ }
+ pids[slot] = -1;
+ }
+
+ preserve = PRESERVE;
+ pid = wait(&preserve);
+ if (pid >= 0) {
+ REPORT_MISC("phantom menace");
+ goto fail;
+ }
+ if (preserve != PRESERVE) {
+ REPORT_MISC("obliteration");
+ goto fail;
+ }
+
+ REPORT_END_SUCCESS;
+ exit(0);
+
+fail:
+ REPORT_END_FAIL;
+ exit(9);
+}
+
+void
+child(int which)
+{
+ int wpid, gpid;
+ char msg[128];
+
+ snprintf(msg, sizeof (msg), "child %d", which);
+ printf("%s\n", msg);
+ REPORT_MISC(msg);
+
+ switch(((gpid = fork()) < 0) ? -1 : gpid) {
+ case -1:
+ REPORT_MISC("child cannot fork");
+ goto fail;
+ break;
+ case 0:
+ if (which & 1) {
+ yield(-1);
+ yield(-1);
+ }
+ exit(0);
+ default:
+ if ((which & 4) != 4) {
+ if ((wpid = wait(0)) != gpid) {
+ REPORT_MISC("grandchild??");
+ goto fail;
+ }
+ }
+ exit(which);
+ break;
+ }
+
+fail:
+ exit(-1);
+}
diff --git a/410user/progs/bg.c b/410user/progs/bg.c
new file mode 100644
index 0000000..feccf37
--- /dev/null
+++ b/410user/progs/bg.c
@@ -0,0 +1,39 @@
+/** @file 410user/progs/bg.c
+ * @author mjsulliv (2009)
+ * @brief runs a command in the background
+ * @public yes
+ * @for p3,p4
+ * @covers fork
+ * @bug This should arguably be done by the shell.
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char *argv[])
+{
+ int pid;
+
+ if (argv[argc]) printf("*** fsck: %p!\n", argv[argc]);
+
+ if (argc < 2) {
+ printf("usage: %s program [arguments]\n", argv[0]);
+ return 1;
+ }
+
+ if ((pid = fork()) > 0) {
+ printf("Child pid: %d\n", pid);
+ return 0;
+ } else if (pid < 0) {
+ return 1;
+ }
+
+ /* Now we are a child, our parent is exiting, so we will be owned by init.
+ * The shell was waiting on our parent and doesn't give a hoot about us. */
+
+ int ret = exec(argv[1], &argv[1]);
+ panic("exec failed: %d!", ret);
+
+ return 0;
+}
diff --git a/410user/progs/bistromath.c b/410user/progs/bistromath.c
new file mode 100644
index 0000000..9b63047
--- /dev/null
+++ b/410user/progs/bistromath.c
@@ -0,0 +1,7711 @@
+/******************************************************************************
+ * This is a port of the chess engine "bistromath" to the Pebbles kernel.
+ * Both the original and the port are copyright Ben Blum <bblum@andrew.cmu.edu>
+ * 2013, all rights reserved.
+ *
+ * Readers interested in the inner workings of the chess engine will be much
+ * happier navigating the original codebase, where the files are not all
+ * concatenated together.
+ *
+ * ====> http://bblum.net/bistromath.tar.bz2 <====
+ *
+ * The pebbles glue / console interface (which are obviously not present in the
+ * original version) are at the bottom of this file, around line 7050.
+ *
+ * This program incidentally tests for the following Pebbles functionalities:
+ * - Loading very large ELFs (.bss comes out to be about 192MB)
+ * - Stack growth (each ply searched takes a little over 32KB of stack)
+ * - Simple threading -- another thread is used for the search timer
+ *
+ * Please direct all questions/bugs to Ben Blum <bblum@andrew.cmu.edu>.
+ *
+ ******************************************************************************
+ *
+ * This code is licensed under the GNU Library GPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "rand.h"
+#include "thread.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) ((sizeof(a))/(sizeof(a[0])))
+#endif
+
+/****************************************************************************
+ * attacks.h - precomputed attack-/move-mask tables
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef ATTACKS_H
+#define ATTACKS_H
+
+#define U64(x) ((uint64_t)(x ## ull))
+#define U32(x) ((uint32_t)(x))
+
+extern uint64_t knightattacks[64];
+extern uint64_t kingattacks[64];
+extern uint64_t pawnattacks[2][64];
+extern uint64_t pawnmoves[2][64];
+
+extern uint64_t rowattacks[256][8];
+extern uint64_t colattacks[256][8];
+
+extern int rot45diagindex[64];
+extern int rot315diagindex[64];
+
+extern int rot45index_shiftamountright[15];
+extern int rot315index_shiftamountright[15];
+extern int rot315index_shiftamountleft[15];
+
+extern int rotresult_shiftamountleft[15];
+extern int rotresult_shiftamountright[15];
+
+uint64_t rot45attacks[256][8];
+uint64_t rot315attacks[256][8];
+
+#endif
+/****************************************************************************
+ * bitscan.h - useful for switching bitscan implementations
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef BITSCAN_H
+#define BITSCAN_H
+
+#define BITSCAN(x) (ffsll(x)-1)
+
+#endif
+
+// Below are ffs.c and ffsll.c from a standard glibc distribution, since 410user
+// doesn't have them.
+
+/* Copyright (C) 1991, 1992, 1997, 1998, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Torbjorn Granlund (tege@sics.se).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define ffs(x) __ffs(x)
+
+/* Find the first bit set in I. */
+int
+__ffs (i)
+ int i;
+{
+ static const unsigned char table[] =
+ {
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 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,
+ 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,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+ };
+ unsigned int a;
+ unsigned int x = i & -i;
+
+ a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
+
+ return table[x >> a] + a;
+}
+/* Copyright (C) 1991, 1992, 1997, 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Torbjorn Granlund (tege@sics.se).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Find the first bit set in I. */
+int
+ffsll (i)
+ long long int i;
+{
+ unsigned long long int x = i & -i;
+
+ if (x <= 0xffffffff)
+ return ffs (i);
+ else
+ return 32 + ffs (i >> 32);
+}
+
+/****************************************************************************
+ * popcnt.h - various population-count implementations
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef POPCNT_H
+#define POPCNT_H
+
+/* Can be used to change which implementation we use */
+//#define POPCOUNT(x) popcnt3(x)
+#define POPCOUNT(x) popcnt2(x)
+
+/**
+ * Returns a count of how many bits are set in the argument.
+ */
+int popcnt(uint64_t);
+
+/**
+ * Alternative implementations
+ */
+int popcnt2(uint64_t);
+int popcnt3(uint64_t);
+
+#endif
+/****************************************************************************
+ * rand.h - wrappers for random number generation utilities
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+/* Set up the random number generator */
+void rand_init();
+/* A "random" 32-bit integer as provided by GSL's mersenne twister */
+uint32_t rand32();
+/* A "random" 64-bit integer as provided by GSL's mersenne twister */
+uint64_t rand64();
+
+/****************************************************************************
+ * movelist.h - data structure for move sorting in move generation/iteration
+ * copyright (C) 2008 Ben Blum
+ * ****************************************************************************/
+#ifndef MOVELIST_H
+#define MOVELIST_H
+
+
+#define MOVELIST_NUM_BUCKETS 64
+#define MOVELIST_SUBLIST_LENGTH 128
+
+/****************************************************************************
+ * Our move ordering scheme will look something like this:
+ *
+ * 00-08: Moves that lose material
+ * 00: -9 (Q hang)
+ * 01: -8 (Qx protected P)
+ * 02: -7 (None)
+ * 03: -6 (Qx protected B/N)
+ * 04: -5 (R hang)
+ * 05: -4 (Qx protected R)
+ * 06: -3 (B/N hang)
+ * 07: -2 (Bx/Nx protected P, Rx protected B/N)
+ * 08: -1 (P hang)
+ * 9-41: Regular moves, indexed by piecetable[dest] - piecetable[src] + 25
+ * 42: Minor promotions
+ * 43: O-O-O
+ * 44: O-O
+ * 45-49: Neutral captures
+ * 45: PxP
+ * 46: NxN
+ * 47: BxB
+ * 48: RxR
+ * 49: QxQ
+ * 50-58: Moves that win material
+ * 50: +1 (P unhang, *x hung P)
+ * 51: +2 (Px protected B/N, Bx/Nx protected R)
+ * 52: +3 (B/N unhang, *x hung B/N)
+ * 53: +4 (Px protected R)
+ * 54: +5 (R unhang, *x hung B/N)
+ * 55: +6 (Bx/Nx protected Q)
+ * 56: +7 (None)
+ * 57: +8 (Px protected Q)
+ * 58: +9 (Q unhang, *x hung Q)
+ * 59: Promotions to queen
+ * 60: Promotions to queen with capture
+ * 61: K unhang
+ ****************************************************************************/
+
+/* starting index for moves that lose material - subtract how much is lost */
+#define MOVELIST_INDEX_MAT_LOSS 9
+/* regular move - add the piece/square table difference */
+#define MOVELIST_INDEX_REGULAR 25
+/* minor promotion - the thought behind this is if the Q promotion is wrong,
+ * probably this will be too, so try other moves first */
+#define MOVELIST_INDEX_PROM_MINOR 42
+/* castle - add 1 if kingside */
+#define MOVELIST_INDEX_CASTLE 43
+/* neutral capture - add the piece number (P=0 ... Q=4) */
+#define MOVELIST_INDEX_NEUTRAL 45
+/* moves that win material - add how much is gained */
+#define MOVELIST_INDEX_MAT_GAIN 49
+/* promotion to queen - add one if it's also a capture */
+#define MOVELIST_INDEX_PROM_QUEEN 59
+
+/**
+ * The movelist_t data structure is a generalization of maintaining multiple
+ * linkedlists and appending them at the end for O(n) pseudo-sorting - it
+ * allows an arbitrary number of lists for sorting into that many buckets,
+ * with the only constraints being 1) space and 2) time to move the "max"
+ * index to point to the next bucket when one bucket is empty. The result is
+ * O(n) sorting during creation (beating O(n^2 logn)), but an additional O(m)
+ * coefficient for both space and time complexity, so choose a small m!
+ */
+typedef struct {
+ uint32_t array[MOVELIST_NUM_BUCKETS][MOVELIST_SUBLIST_LENGTH];
+ int sublist_count[MOVELIST_NUM_BUCKETS];
+ /* highest index of a bucket which contains elements; note, if
+ * array[max] is empty, that means the whole movelist is empty */
+ unsigned long max;
+} movelist_inner_t;
+
+typedef movelist_inner_t *movelist_t;
+
+/* Movelist's max should be zero, each array should be zero, and each
+* array should have a count of zero. */
+static inline void movelist_init(movelist_t *ml)
+{
+ *ml = malloc(sizeof(movelist_inner_t));
+ affirm_msg(*ml, "Couldn't allocate memory to generate moves");
+ memset((*ml)->sublist_count, 0, MOVELIST_NUM_BUCKETS*sizeof(int));
+ (*ml)->max = 0;
+}
+
+#define movelist_destroy(mlp) do { free(*mlp); } while (0)
+
+void movelist_add(movelist_t *, uint64_t[2], uint32_t);
+void movelist_addtohead(movelist_t *, uint32_t, unsigned long);
+int movelist_isempty(movelist_t *);
+uint32_t movelist_remove_max(movelist_t *);
+
+#endif
+
+/****************************************************************************
+ * board.h - rotated bitboard library; move generation and board state
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef BOARD_H
+#define BOARD_H
+
+/**
+ * Piece/color constants. Used as indices to get the position bitboard of a
+ * given piece of a given color, among other things.
+ */
+#define WHITE 0
+#define BLACK 1
+
+/* The color not thise one. Equivalent to "x == WHITE ? BLACK : WHITE" */
+#define OTHERCOLOR(x) (1^(x))
+/* This player's home-rank (0 for white, 7 for black) */
+#define HOMEROW(x) ((x == WHITE) ? 0 : 7)
+
+/* Piece types */
+#define PAWN 0x0
+#define KNIGHT 0x1
+#define BISHOP 0x2
+#define ROOK 0x3
+#define QUEEN 0x4
+#define KING 0x5
+#define PIECE_SLIDES(p) (((p) > KNIGHT) && ((p) < KING))
+typedef uint8_t piece_t;
+
+extern char *piecename[2][6];
+
+/**
+ * Square constants. 6 lowest bits: |0|0|r|o|w|c|o|l|
+ * These can serve as indexes to get bits out of a bitboard. Also used to get
+ * masks for sliding pieces by row/etc
+ */
+#define A1 0x00
+#define B1 0x01
+#define C1 0x02
+#define D1 0x03
+#define E1 0x04
+#define F1 0x05
+#define G1 0x06
+#define H1 0x07
+#define A2 0x08
+#define B2 0x09
+#define C2 0x0a
+#define D2 0x0b
+#define E2 0x0c
+#define F2 0x0d
+#define G2 0x0e
+#define H2 0x0f
+#define A3 0x10
+#define B3 0x11
+#define C3 0x12
+#define D3 0x13
+#define E3 0x14
+#define F3 0x15
+#define G3 0x16
+#define H3 0x17
+#define A4 0x18
+#define B4 0x19
+#define C4 0x1a
+#define D4 0x1b
+#define E4 0x1c
+#define F4 0x1d
+#define G4 0x1e
+#define H4 0x1f
+#define A5 0x20
+#define B5 0x21
+#define C5 0x22
+#define D5 0x23
+#define E5 0x24
+#define F5 0x25
+#define G5 0x26
+#define H5 0x27
+#define A6 0x28
+#define B6 0x29
+#define C6 0x2a
+#define D6 0x2b
+#define E6 0x2c
+#define F6 0x2d
+#define G6 0x2e
+#define H6 0x2f
+#define A7 0x30
+#define B7 0x31
+#define C7 0x32
+#define D7 0x33
+#define E7 0x34
+#define F7 0x35
+#define G7 0x36
+#define H7 0x37
+#define A8 0x38
+#define B8 0x39
+#define C8 0x3a
+#define D8 0x3b
+#define E8 0x3c
+#define F8 0x3d
+#define G8 0x3e
+#define H8 0x3f
+typedef uint8_t square_t;
+
+/* Converts int to string. Better than using malloc for 3-length strings. */
+extern char *squarename[64];
+
+#define RANK_1 0
+#define RANK_2 1
+#define RANK_3 2
+#define RANK_4 3
+#define RANK_5 4
+#define RANK_6 5
+#define RANK_7 6
+#define RANK_8 7
+#define COL_A 0
+#define COL_B 1
+#define COL_C 2
+#define COL_D 3
+#define COL_E 4
+#define COL_F 5
+#define COL_G 6
+#define COL_H 7
+
+/* converting square <--> (column,row) */
+#define COL(s) ((s) & 0x7) /* 0<=s<64 */
+#define ROW(s) ((s) >> 3) /* 0<=s<64 */
+#define SQUARE(c,r) ((square_t)((c) | ((r) << 3))) /* 0<=c,r<8 */
+/* what color is the square - 1 or 0, not necessarily BLACK or WHITE */
+#define PARITY(s) ((COL(s) + ROW(s)) & 0x1)
+
+/* Used mostly as array indices, especially for castling */
+#define QUEENSIDE 0
+#define KINGSIDE 1
+/* Given the side of the board, which column will the king end up on */
+#define CASTLE_DEST_COL(x) (((x) == QUEENSIDE) ? COL_C : COL_G)
+
+/* Constants for board_mated return values */
+#define BOARD_CHECKMATED 1
+#define BOARD_STALEMATED 2
+
+/**
+ * move_t will contain a src square (lowest 6 bits), a dest square (next 6
+ * bits), and several flags - is check, isenpassant, iscapture (and what
+ * piece type is captured), ispromotion (and what is promoted to), and
+ * also which color made the move.
+ * 000000 JJJ III HHH G F E D C BBBBBB AAAAAA
+ * 26 23 20 17 16 15 14 13 12 6 0
+ * A: Source square
+ * B: Dest square
+ * C: Color (which side is making this move)
+ * D: Castle
+ * E: En passant
+ * F: Capture
+ * G: Promotion
+ * H: Captured piece type (color will be the opposite of C)
+ * I: Promotion result piece type (color indicated by C)
+ * J: Which piece type is moving (color indicated by C)
+ * 0: Unused bits
+ * Note: Bits 25 and up are used for the repetition count in the transposition
+ * table; see transposition.{h,c}
+ */
+typedef uint32_t move_t;
+#define MOV_INDEX_SRC 0
+#define MOV_INDEX_DEST 6
+#define MOV_INDEX_COLOR 12
+#define MOV_INDEX_CASTLE 13
+#define MOV_INDEX_EP 14
+#define MOV_INDEX_CAPT 15
+#define MOV_INDEX_PROM 16
+#define MOV_INDEX_CAPTPC 17
+#define MOV_INDEX_PROMPC 20
+#define MOV_INDEX_PIECE 23
+#define MOV_INDEX_UNUSED 26
+
+#define MOV_SRC(m) ((square_t)(((m) >> MOV_INDEX_SRC) & 0x3f))
+#define MOV_DEST(m) ((square_t)(((m) >> MOV_INDEX_DEST) & 0x3f))
+#define MOV_COLOR(m) (((m) >> MOV_INDEX_COLOR) & 0x1)
+#define MOV_CASTLE(m) (((m) >> MOV_INDEX_CASTLE) & 0x1)
+#define MOV_EP(m) (((m) >> MOV_INDEX_EP) & 0x1)
+#define MOV_CAPT(m) (((m) >> MOV_INDEX_CAPT) & 0x1)
+#define MOV_PROM(m) (((m) >> MOV_INDEX_PROM) & 0x1)
+#define MOV_CAPTPC(m) ((piece_t)(((m) >> MOV_INDEX_CAPTPC) & 0x7))
+#define MOV_PROMPC(m) ((piece_t)(((m) >> MOV_INDEX_PROMPC) & 0x7))
+#define MOV_PIECE(m) ((piece_t)(((m) >> MOV_INDEX_PIECE) & 0x7))
+
+/**
+ * 64-bit representation of a board's state for one set of piece, also used
+ * for representing attacks, regions of the board, ...
+ */
+typedef uint64_t bitboard_t;
+
+/**
+ * Zobrist hash key
+ */
+typedef uint64_t zobrist_t;
+
+/* Upper bound on how many halfmoves a game should take. Memory is cheap. */
+#define HISTORY_STACK_SIZE 2048
+
+/**
+ * Nonrecomputable state stored on the history stack when a move is made
+ */
+typedef struct {
+ zobrist_t hash;
+ bitboard_t attackedby[2];
+ unsigned char castle[2][2];
+ square_t ep;
+ unsigned char halfmoves;
+ unsigned char reps;
+ move_t move;
+} history_t;
+
+/****************************************************************************
+ * Representation of an entire board state.
+ * The pos[][] array represents standard normal-oriented setups, accessed by
+ * piece and color. Normally oriented bitboards look like this:
+ *
+ * (64-bit format by square)
+ * H8 G8 F8 E8 D8 C8 B8 A8 H7 G7 ... A2 H1 G1 F1 E1 D1 C1 B1 A1
+ * 63 62 61 60 59 58 57 56 55 54 ... 8 7 6 5 4 3 2 1 0
+ *
+ * (8x8 format by index (from the least significant bit))
+ * -------------------------
+ * 8 | 56 57 58 59 60 61 62 63 |
+ * 7 | ... 54 55 |
+ * | ... |
+ * 3 | 16 17 ... |
+ * 2 | 8 9 10 11 12 13 14 15 |
+ * 1 | 0 1 2 3 4 5 6 7 |
+ * -------------------------
+ * a b c d e f g h
+ *
+ * The n-th index row (0 for 1, 7 for 8) can be extracted by
+ * "(bitboard >> (8*n)) & 0xFF". The rotated boards are slightly different.
+ * Rot90, used for rook attacks, looks like this:
+ *
+ * H8 H7 H6 H5 H4 H3 H2 H1 G8 G7 ... B1 A8 A7 A6 A5 A4 A3 A2 A1
+ * 63 62 61 60 59 58 57 56 55 54 ... 8 7 6 5 4 3 2 1 0
+ *
+ * -------------------------
+ * h | 56 57 58 59 60 61 62 63 |
+ * g | ... 54 55 |
+ * | ... |
+ * c | 16 17 ... |
+ * b | 8 9 10 11 12 13 14 15 |
+ * a | 0 1 2 3 4 5 6 7 |
+ * -------------------------
+ * 1 2 3 4 5 6 7 8
+ *
+ * So the n-th index file (0 for a, 7 for h) can be obtained easily. Note that
+ * "rot90" is a lie, it's actually flipped across the a1-h8 diagonal. For
+ * bishops, we rotate so squares on a single diagonal are adjacent.
+ * rot45: rot315:
+ * ,--, 8 ,--,
+ * ,' 63 ', 7 ,' 63 ',
+ * ,' 61 62 ', 6 ,' 61 62 ',
+ * ,' 58 59 60 ', 5 ,' 58 59 60 ',
+ * ,' 54 55 56 57 ', 4 ,' 54 55 56 57 ',
+ * ,' 49 50 51 52 53 ', 3 ,' 49 50 51 52 53 ',
+ * ,' 43 44 45 46 47 48 ', 2 ,' 43 44 45 46 47 48 ',
+ * ,' 36 37 38 39 40 41 42 ', 1 ,' 36 37 38 39 40 41 42 ',
+ * ( 28 29 30 31 32 33 34 35 ) ( 28 29 30 31 32 33 34 35 )
+ * 8 ', 21 22 23 24 25 26 27 ,' h a ', 21 22 23 24 25 26 27 ,'
+ * 7 ', 15 16 17 18 19 20 ,' g b ', 15 16 17 18 19 20 ,'
+ * 6 ', 10 11 12 13 14 ,' f c ', 10 11 12 13 14 ,'
+ * 5 ', 06 07 08 09 ,' e d ', 06 07 08 09 ,'
+ * 4 ', 03 04 05 ,' d e ', 03 04 05 ,'
+ * 3 ', 01 02 ,' c f ', 01 02 ,'
+ * 2 ', 00 ,' b g ', 00 ,'
+ * 1 '--' a h '--'
+ * Diagonals are "numbered" 0 to 14 (15 in total); in each diagram the diag
+ * on the bottom will be #0, the major diagonal will be #7, and the top #14.
+ * See precomputed.h for values and macros relating to this implementation.
+ ****************************************************************************/
+typedef struct {
+ /* These arrays contain basic information about where the pieces are
+ * on the board. Used generally for masking with attack bitboards. */
+ bitboard_t pos[2][6]; /* Positions of each PIECE of COLOR */
+ bitboard_t piecesofcolor[2]; /* All squares occupied by COLOR */
+ bitboard_t attackedby[2]; /* All squares attacked by COLOR */
+ /* Maintain the occupancy status of every square on the board in four
+ * rotated boards, for easy generation of sliding attacks. */
+ bitboard_t occupied;
+ bitboard_t occupied90;
+ bitboard_t occupied45;
+ bitboard_t occupied315;
+ /* The zobrist hash key for the current position */
+ zobrist_t hash;
+ /* Stores nonrecomputable state for undo. Index into with ->moves. */
+ history_t history[HISTORY_STACK_SIZE];
+ /* Various flags relating to the current position. Note for the ep
+ * flag that the capture square will always be on the 3rd (2-index)
+ * row, or the 6th (5-index) row. A value of zero means no enpassant
+ * is possible in this position. */
+ square_t ep; /* The square on which an ep capture
+ * could occur */
+ unsigned char castle[2][2]; /* Can {WHITE,BLACK} castle {KINGSIDE,
+ * QUEENSIDE} */
+ unsigned char hascastled[2]; /* has {WHITE,BLACK} castled yet */
+ unsigned char tomove; /* Who has the move (WHITE, BLACK) */
+ unsigned char halfmoves; /* The halfmove clock. A draw occurs when
+ * this hits 100. */
+ unsigned int moves; /* The game move clock. This also counts
+ * halfmoves, but is never reset. */
+ unsigned char reps; /* how many times has this position
+ * appeared before? if 2, draw */
+ int16_t material[2]; /* keeps track of material; see eval.c */
+} board_t;
+
+/****************************************************************************
+ * Some special macros and precomputed bitboards
+ ****************************************************************************/
+#define BB(b) ((bitboard_t)(b ## ull))
+#define BB_FILEA BB(0x0101010101010101)
+#define BB_FILEB BB(0x0202020202020202)
+#define BB_FILEC BB(0x0404040404040404)
+#define BB_FILED BB(0x0808080808080808)
+#define BB_FILEE BB(0x1010101010101010)
+#define BB_FILEF BB(0x2020202020202020)
+#define BB_FILEG BB(0x4040404040404040)
+#define BB_FILEH BB(0x8080808080808080)
+#define BB_FILE(c) (BB_FILEA << (c))
+#define BB_RANK1 BB(0x00000000000000ff)
+#define BB_RANK2 BB(0x000000000000ff00)
+#define BB_RANK3 BB(0x0000000000ff0000)
+#define BB_RANK4 BB(0x00000000ff000000)
+#define BB_RANK5 BB(0x000000ff00000000)
+#define BB_RANK6 BB(0x0000ff0000000000)
+#define BB_RANK7 BB(0x00ff000000000000)
+#define BB_RANK8 BB(0xff00000000000000)
+#define BB_RANK(r) (BB_RANK1 << (8 * (r)))
+#define BB_HALF_RANKS(s) (((s) == WHITE) ? BB(0x00000000ffffffff) : BB(0xffffffff00000000))
+#define BB_HALF_FILES(s) (((s) == QUEENSIDE) ? BB(0x0f0f0f0f0f0f0f0f) : BB(0xf0f0f0f0f0f0f0f0))
+
+
+/* pawnstructure needs these */
+extern bitboard_t bb_adjacentcols[8];
+extern bitboard_t bb_passedpawnmask[2][64];
+
+/* BB_SQUARE: Get a bitboard with only one bit set, on a specified square
+ * Bb_ALLEXCEPT: The bitwise negation of BB_SQUARE(x) */
+//#define BB_SHIFTFLIP /* prefer shift/flip to cached memory lookups */
+#ifdef BB_SHIFTFLIP
+ #define BB_SQUARE(x) BB((BB(0x1))<<(x))
+ #define BB_ALLEXCEPT(x) BB(~(BB_SQUARE(x)))
+#else
+ #define BB_SQUARE(x) bb_square[x]
+ #define BB_ALLEXCEPT(x) bb_allexcept[x]
+ extern bitboard_t bb_square[64];
+ extern bitboard_t bb_allexcept[64];
+#endif
+
+/* If you are {white,black}, you ep-capture with a pawn on rank {5,4} */
+#define BB_EP_FROMRANK(c) (((c) == WHITE) ? BB_RANK5 : BB_RANK4)
+/* If you are {white,black}, your pawn will be ep-captured on {3,6} */
+#define BB_EP_TORANK(c) (((c) == WHITE) ? BB_RANK3 : BB_RANK6)
+
+/****************************************************************************
+ * Function declarations
+ ****************************************************************************/
+void init_zobrist();
+void zobrist_gen(board_t *);
+
+board_t *board_init();
+void board_destroy(board_t *);
+char *board_fen(board_t *);
+piece_t board_pieceatsquare(board_t *, square_t, unsigned char *);
+int board_incheck(board_t *);
+int board_colorincheck(board_t *, unsigned char);
+int board_mated(board_t *);
+int board_pawnpassed(board_t *, square_t, unsigned char);
+int board_squareisattacked(board_t *, square_t, unsigned char);
+int board_squaresareattacked(board_t *, bitboard_t, unsigned char);
+bitboard_t board_attacksfrom(board_t *, square_t, piece_t, unsigned char);
+bitboard_t board_pawnpushesfrom(board_t *, square_t, unsigned char);
+void board_generatemoves(board_t *, movelist_t *);
+void board_generatecaptures(board_t *, movelist_t *);
+void board_applymove(board_t *, move_t);
+void board_undomove(board_t *, move_t);
+bitboard_t board_pawnattacks(bitboard_t pawns, unsigned char);
+int board_threefold_draw(board_t *);
+
+move_t move_fromstring(char *);
+move_t move_islegal(board_t *, char *, char **);
+char *move_tostring(move_t);
+
+#endif
+/****************************************************************************
+ * eval.h - evaluation function to tell how good a position is
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef EVAL_H
+#define EVAL_H
+
+#ifndef EVAL_LAZY_THRESHHOLD
+#define EVAL_LAZY_THRESHHOLD 250
+#endif
+
+/**
+ * Is this board an endgame position
+ */
+int eval_isendgame(board_t *);
+
+/**
+ * Evaluation function. Given a board, returns an int value representing how
+ * good this position is for whoever has the move. A positive score means the
+ * player to move has the advantage; a negative score means the player to move
+ * has the disadvantage; a zero score means both sides have equal chances.
+ */
+int16_t eval(board_t *);
+
+/**
+ * Lazy eval - just the material difference
+ */
+int16_t eval_lazy(board_t *);
+
+#endif
+/****************************************************************************
+ * pawnstructure.h - evaluation helpers to judge pawn structure quality
+ * copyright (C) 2008 Ben Blum
+ * ****************************************************************************/
+#ifndef PAWNSTRUCTURE_H
+#define PAWNSTRUCTURE_H
+
+/**
+ * Evaluate the pawn structure given the position bitboard for the pawns. We
+ * don't want to consider anything besides the position of the pawns relative
+ * to each other - this just assigns rewards and penalties for pawn-related
+ * issues such as doubled pawns, isolated pawns, etcetera.
+ * Pass in the pawn position bitboard and the color to whom these pwans belong
+ */
+int16_t eval_pawnstructure(board_t *, unsigned char, bitboard_t *);
+
+#endif
+/****************************************************************************
+ * quiescent.h - captures-only search to avoid evaluating unstable position
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef QUIESCENT_H
+#define QUIESCENT_H
+
+int16_t quiesce(board_t *board, int16_t alpha, int16_t beta);
+
+#endif
+/****************************************************************************
+ * transposition.h - avoid re-searching already searched positions
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef TRANSPOSITION_H
+#define TRANSPOSITION_H
+
+/**
+ * Transposition table - keyed by zobrist hash, stores info about a node. We
+ * keep track of the following data:
+ * 1) The best move at this position (possibly 0, if a fail-low occurred)
+ * 2) The evaluated (or approximate) value of the position
+ * 3) The depth this node was searched to, or -1 if this was {check,stale}mate
+ * Note we use -1 (as an unsigned depth value) so that we will always use
+ * transposition information for terminal nodes rather than wasting time
+ * figuring out how big the movelist is.
+ * 4) How far into the game (not search tree) this position is. This data lets
+ * us always evict nodes beyond which the state of the game has gone. Note,
+ * 5) What type of values these are:
+ * Exact value
+ * Beta cutoff - failed high (storedval is lower bound)
+ * Alpha cutoff - failed low (storedval is upper bound)
+ *
+ * Note: The "depth" should not be simply the depth to which this node was
+ * searched. It should be instead that depth plus how far into the game we are
+ * (i.e., the game clock). This will help us replace nodes that are behind our
+ * search tree entirely - otherwise, the table will fill with high-depth nodes
+ * that we'll never use because they were back in the beginning of the game.
+ * When comparing for replacement, use the gamedepth of the root node (the
+ * position currently on the board), but when adding, use the gamedepth of
+ * the current node (the position a few moves in the future). Because of
+ * this the searcher needs to pass both values to trans_add().
+ * Definitions: "search depth" refers to how deep this node will be searched;
+ * "game depth" refer's to THIS NODE's depth in the whole game tree; "root
+ * depth" refers to how deep the position the searcher started at is.
+ */
+typedef struct trans_data_t {
+ /* gcc -O3 optimizes all this into a register;
+ * note, the element ordering is critical */
+ uint8_t flags;
+ uint8_t gamedepth;
+ int16_t value;
+ uint32_t move;
+} trans_data_t;
+/* The 'flags' field stores the alpha/beta/exact flags in two bits and the
+ * searched-depth of the node
+ * BBBBBB AA
+ * 2 0
+ * A: Alpha/beta/exact
+ * B: searchdepth
+ * If we search deeper than 63 plies then we're in trouble.
+ * */
+#define TRANS_FLAG_EXACT 0x2
+#define TRANS_FLAG_BETA 0x1
+#define TRANS_FLAG_ALPHA 0x0
+/* Conversion macros - see trans_data() in trans.c for the other direction */
+#define TRANS_INDEX_FLAG 0
+#define TRANS_INDEX_SEARCHDEPTH 2
+#define TRANS_FLAG(t) (((t).flags >> TRANS_INDEX_FLAG) & 0x3)
+#define TRANS_SEARCHDEPTH(t) (((t).flags >> TRANS_INDEX_SEARCHDEPTH) & 0x3f)
+#define TRANS_GAMEDEPTH(t) ((t).gamedepth)
+#define TRANS_VALUE(t) ((t).value)
+#define TRANS_MOVE(t) ((t).move & ((1 << MOV_INDEX_UNUSED) - 1))
+#define TRANS_REPS(t) ((t).move >> MOV_INDEX_UNUSED)
+
+/* Add an entry. On collision, will succeed only if it's better information */
+void trans_add(zobrist_t, move_t, uint8_t, int16_t, uint8_t, uint8_t, uint8_t,
+ unsigned char);
+/* Find a value from the table. Returns -1 if none exists - you can trust this
+ * value because a trans_data_t will never be -1 due to the blank bits */
+trans_data_t trans_get(zobrist_t);
+/* Check if the return value from get() was valid */
+int trans_data_valid(trans_data_t);
+
+#endif
+/****************************************************************************
+ * book.h - simple interface for retrieving moves from a plaintext book
+ * copyright (C) 2008 Ben Blum
+ * ****************************************************************************/
+#ifndef BOOK_H
+#define BOOK_H
+
+#define BOOK_LINE_MAX_LENGTH 256
+
+move_t book_move(char *line, board_t *board);
+
+#endif
+/****************************************************************************
+ * search.h - traverse the game tree looking for the best position
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef SEARCH_H
+#define SEARCH_H
+
+/**
+ * A search function will require the following arguments:
+ * 1) Board state
+ * 2) How many seconds we should think before moving
+ * 3) int * - if nonnull, lets you know how many nodes were searched
+ * 4) int * - if nonnull, lets you know the alpha value of the position
+ */
+typedef move_t (*search_fn)(board_t *, unsigned int, int *, int16_t *);
+
+move_t getbestmove(board_t *, unsigned int, int *, int16_t *);
+
+#endif
+/****************************************************************************
+ * engine.c - wrapper functions for managing computer vs human play
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+#ifndef ENGINE_H
+#define ENGINE_H
+
+
+#define ENGINE_NAME "bistromath"
+
+typedef struct engine_t {
+ board_t *board;
+ search_fn search;
+ char line[BOOK_LINE_MAX_LENGTH];
+ unsigned int line_moves;
+ unsigned char inbook;
+} engine_t;
+
+engine_t *engine_init(search_fn);
+char *engine_generatemove(engine_t *);
+int engine_applymove(engine_t *, char *, char **);
+void engine_destroy(engine_t *);
+
+#endif
+/****************************************************************************
+ * attacks.c - precomputed attack-/move-mask tables
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+/* Bitmasks for attackable squares given a square a certain piece is on. Use
+ * the predefined constants (A1 to H8, 0-63) from bitboard.h, or some other
+ * way of getting the square in the same format, to index into these arrays */
+uint64_t knightattacks[64] = {
+ /* A1 to H1 */
+ U64(0x0000000000020400), U64(0x0000000000050800), U64(0x00000000000a1100), U64(0x0000000000142200),
+ U64(0x0000000000284400), U64(0x0000000000508800), U64(0x0000000000a01000), U64(0x0000000000402000),
+ /* A2 to H2 */
+ U64(0x0000000002040004), U64(0x0000000005080008), U64(0x000000000a110011), U64(0x0000000014220022),
+ U64(0x0000000028440044), U64(0x0000000050880088), U64(0x00000000a0100010), U64(0x0000000040200020),
+ /* A3 to H3 */
+ U64(0x0000000204000402), U64(0x0000000508000805), U64(0x0000000a1100110a), U64(0x0000001422002214),
+ U64(0x0000002844004428), U64(0x0000005088008850), U64(0x000000a0100010a0), U64(0x0000004020002040),
+ /* A4 to H4 */
+ U64(0x0000020400040200), U64(0x0000050800080500), U64(0x00000a1100110a00), U64(0x0000142200221400),
+ U64(0x0000284400442800), U64(0x0000508800885000), U64(0x0000a0100010a000), U64(0x0000402000204000),
+ /* A5 to H5 */
+ U64(0x0002040004020000), U64(0x0005080008050000), U64(0x000a1100110a0000), U64(0x0014220022140000),
+ U64(0x0028440044280000), U64(0x0050880088500000), U64(0x00a0100010a00000), U64(0x0040200020400000),
+ /* A6 to H6 */
+ U64(0x0204000402000000), U64(0x0508000805000000), U64(0x0a1100110a000000), U64(0x1422002214000000),
+ U64(0x2844004428000000), U64(0x5088008850000000), U64(0xa0100010a0000000), U64(0x4020002040000000),
+ /* A7 to H7 */
+ U64(0x0400040200000000), U64(0x0800080500000000), U64(0x1100110a00000000), U64(0x2200221400000000),
+ U64(0x4400442800000000), U64(0x8800885000000000), U64(0x100010a000000000), U64(0x2000204000000000),
+ /* A8 to H8 */
+ U64(0x0004020000000000), U64(0x0008050000000000), U64(0x00110a0000000000), U64(0x0022140000000000),
+ U64(0x0044280000000000), U64(0x0088500000000000), U64(0x0010a00000000000), U64(0x0020400000000000)
+};
+uint64_t kingattacks[64] = {
+ /* A1 to H1 */
+ U64(0x0000000000000302), U64(0x0000000000000705), U64(0x0000000000000e0a), U64(0x0000000000001c14),
+ U64(0x0000000000003828), U64(0x0000000000007050), U64(0x000000000000e0a0), U64(0x000000000000c040),
+ /* A2 to H2 */
+ U64(0x0000000000030203), U64(0x0000000000070507), U64(0x00000000000e0a0e), U64(0x00000000001c141c),
+ U64(0x0000000000382838), U64(0x0000000000705070), U64(0x0000000000e0a0e0), U64(0x0000000000c040c0),
+ /* A3 to H3 */
+ U64(0x0000000003020300), U64(0x0000000007050700), U64(0x000000000e0a0e00), U64(0x000000001c141c00),
+ U64(0x0000000038283800), U64(0x0000000070507000), U64(0x00000000e0a0e000), U64(0x00000000c040c000),
+ /* A4 to H4 */
+ U64(0x0000000302030000), U64(0x0000000705070000), U64(0x0000000e0a0e0000), U64(0x0000001c141c0000),
+ U64(0x0000003828380000), U64(0x0000007050700000), U64(0x000000e0a0e00000), U64(0x000000c040c00000),
+ /* A5 to H5 */
+ U64(0x0000030203000000), U64(0x0000070507000000), U64(0x00000e0a0e000000), U64(0x00001c141c000000),
+ U64(0x0000382838000000), U64(0x0000705070000000), U64(0x0000e0a0e0000000), U64(0x0000c040c0000000),
+ /* A6 to H6 */
+ U64(0x0003020300000000), U64(0x0007050700000000), U64(0x000e0a0e00000000), U64(0x001c141c00000000),
+ U64(0x0038283800000000), U64(0x0070507000000000), U64(0x00e0a0e000000000), U64(0x00c040c000000000),
+ /* A7 to H7 */
+ U64(0x0302030000000000), U64(0x0705070000000000), U64(0x0e0a0e0000000000), U64(0x1c141c0000000000),
+ U64(0x3828380000000000), U64(0x7050700000000000), U64(0xe0a0e00000000000), U64(0xc040c00000000000),
+ /* A8 to H8 */
+ U64(0x0203000000000000), U64(0x0507000000000000), U64(0x0a0e000000000000), U64(0x141c000000000000),
+ U64(0x2838000000000000), U64(0x5070000000000000), U64(0xa0e0000000000000), U64(0x40c0000000000000)
+};
+uint64_t pawnattacks[2][64] = {
+ { /* WHITE */
+ /* A1 to H1 */
+ U64(0x0000000000000200), U64(0x0000000000000500), U64(0x0000000000000a00), U64(0x0000000000001400),
+ U64(0x0000000000002800), U64(0x0000000000005000), U64(0x000000000000a000), U64(0x0000000000004000),
+ /* A2 to H2 */
+ U64(0x0000000000020000), U64(0x0000000000050000), U64(0x00000000000a0000), U64(0x0000000000140000),
+ U64(0x0000000000280000), U64(0x0000000000500000), U64(0x0000000000a00000), U64(0x0000000000400000),
+ /* A3 to H3 */
+ U64(0x0000000002000000), U64(0x0000000005000000), U64(0x000000000a000000), U64(0x0000000014000000),
+ U64(0x0000000028000000), U64(0x0000000050000000), U64(0x00000000a0000000), U64(0x0000000040000000),
+ /* A4 to H4 */
+ U64(0x0000000200000000), U64(0x0000000500000000), U64(0x0000000a00000000), U64(0x0000001400000000),
+ U64(0x0000002800000000), U64(0x0000005000000000), U64(0x000000a000000000), U64(0x0000004000000000),
+ /* A5 to H5 */
+ U64(0x0000020000000000), U64(0x0000050000000000), U64(0x00000a0000000000), U64(0x0000140000000000),
+ U64(0x0000280000000000), U64(0x0000500000000000), U64(0x0000a00000000000), U64(0x0000400000000000),
+ /* A6 to H6 */
+ U64(0x0002000000000000), U64(0x0005000000000000), U64(0x000a000000000000), U64(0x0014000000000000),
+ U64(0x0028000000000000), U64(0x0050000000000000), U64(0x00a0000000000000), U64(0x0040000000000000),
+ /* A7 to H7 */
+ U64(0x0200000000000000), U64(0x0500000000000000), U64(0x0a00000000000000), U64(0x1400000000000000),
+ U64(0x2800000000000000), U64(0x5000000000000000), U64(0xa000000000000000), U64(0x4000000000000000),
+ /* A8 to H8 */
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000)
+ },
+ { /* BLACK */
+ /* A1 to H1 */
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ /* A2 to H2 */
+ U64(0x0000000000000002), U64(0x0000000000000005), U64(0x000000000000000a), U64(0x0000000000000014),
+ U64(0x0000000000000028), U64(0x0000000000000050), U64(0x00000000000000a0), U64(0x0000000000000040),
+ /* A3 to H3 */
+ U64(0x0000000000000200), U64(0x0000000000000500), U64(0x0000000000000a00), U64(0x0000000000001400),
+ U64(0x0000000000002800), U64(0x0000000000005000), U64(0x000000000000a000), U64(0x0000000000004000),
+ /* A4 to H4 */
+ U64(0x0000000000020000), U64(0x0000000000050000), U64(0x00000000000a0000), U64(0x0000000000140000),
+ U64(0x0000000000280000), U64(0x0000000000500000), U64(0x0000000000a00000), U64(0x0000000000400000),
+ /* A5 to H5 */
+ U64(0x0000000002000000), U64(0x0000000005000000), U64(0x000000000a000000), U64(0x0000000014000000),
+ U64(0x0000000028000000), U64(0x0000000050000000), U64(0x00000000a0000000), U64(0x0000000040000000),
+ /* A6 to H6 */
+ U64(0x0000000200000000), U64(0x0000000500000000), U64(0x0000000a00000000), U64(0x0000001400000000),
+ U64(0x0000002800000000), U64(0x0000005000000000), U64(0x000000a000000000), U64(0x0000004000000000),
+ /* A7 to H7 */
+ U64(0x0000020000000000), U64(0x0000050000000000), U64(0x00000a0000000000), U64(0x0000140000000000),
+ U64(0x0000280000000000), U64(0x0000500000000000), U64(0x0000a00000000000), U64(0x0000400000000000),
+ /* A8 to H8 */
+ U64(0x0002000000000000), U64(0x0005000000000000), U64(0x000a000000000000), U64(0x0014000000000000),
+ U64(0x0028000000000000), U64(0x0050000000000000), U64(0x00a0000000000000), U64(0x0040000000000000)
+ }
+};
+/* Don't account for the double-pawn-pushes; the pawn moves generator takes
+ * care of that */
+uint64_t pawnmoves[2][64] = {
+ { /* WHITE */
+ /* A1 to H1 */
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ /* A2 to H2 */
+ U64(0x0000000000010000), U64(0x0000000000020000), U64(0x0000000000040000), U64(0x0000000000080000),
+ U64(0x0000000000100000), U64(0x0000000000200000), U64(0x0000000000400000), U64(0x0000000000800000),
+ /* A3 to H3 */
+ U64(0x0000000001000000), U64(0x0000000002000000), U64(0x0000000004000000), U64(0x0000000008000000),
+ U64(0x0000000010000000), U64(0x0000000020000000), U64(0x0000000040000000), U64(0x0000000080000000),
+ /* A4 to H4 */
+ U64(0x0000000100000000), U64(0x0000000200000000), U64(0x0000000400000000), U64(0x0000000800000000),
+ U64(0x0000001000000000), U64(0x0000002000000000), U64(0x0000004000000000), U64(0x0000008000000000),
+ /* A5 to H5 */
+ U64(0x0000010000000000), U64(0x0000020000000000), U64(0x0000040000000000), U64(0x0000080000000000),
+ U64(0x0000100000000000), U64(0x0000200000000000), U64(0x0000400000000000), U64(0x0000800000000000),
+ /* A6 to H6 */
+ U64(0x0001000000000000), U64(0x0002000000000000), U64(0x0004000000000000), U64(0x0008000000000000),
+ U64(0x0010000000000000), U64(0x0020000000000000), U64(0x0040000000000000), U64(0x0080000000000000),
+ /* A7 to H7 */
+ U64(0x0100000000000000), U64(0x0200000000000000), U64(0x0400000000000000), U64(0x0800000000000000),
+ U64(0x1000000000000000), U64(0x2000000000000000), U64(0x4000000000000000), U64(0x8000000000000000),
+ /* A8 to H8 */
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000)
+ },
+ { /* BLACK */
+ /* A1 to H1 */
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ /* A2 to H2 */
+ U64(0x0000000000000001), U64(0x0000000000000002), U64(0x0000000000000004), U64(0x0000000000000008),
+ U64(0x0000000000000010), U64(0x0000000000000020), U64(0x0000000000000040), U64(0x0000000000000080),
+ /* A3 to H3 */
+ U64(0x0000000000000100), U64(0x0000000000000200), U64(0x0000000000000400), U64(0x0000000000000800),
+ U64(0x0000000000001000), U64(0x0000000000002000), U64(0x0000000000004000), U64(0x0000000000008000),
+ /* A4 to H4 */
+ U64(0x0000000000010000), U64(0x0000000000020000), U64(0x0000000000040000), U64(0x0000000000080000),
+ U64(0x0000000000100000), U64(0x0000000000200000), U64(0x0000000000400000), U64(0x0000000000800000),
+ /* A5 to H5 */
+ U64(0x0000000001000000), U64(0x0000000002000000), U64(0x0000000004000000), U64(0x0000000008000000),
+ U64(0x0000000010000000), U64(0x0000000020000000), U64(0x0000000040000000), U64(0x0000000080000000),
+ /* A6 to H6 */
+ U64(0x0000000100000000), U64(0x0000000200000000), U64(0x0000000400000000), U64(0x0000000800000000),
+ U64(0x0000001000000000), U64(0x0000002000000000), U64(0x0000004000000000), U64(0x0000008000000000),
+ /* A7 to H7 */
+ U64(0x0000010000000000), U64(0x0000020000000000), U64(0x0000040000000000), U64(0x0000080000000000),
+ U64(0x0000100000000000), U64(0x0000200000000000), U64(0x0000400000000000), U64(0x0000800000000000),
+ /* A8 to H8 */
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000),
+ U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000), U64(0x0000000000000000)
+ }
+};
+
+/**
+ * For rook attacks along a row. Uses the 'occupied' status of the row (e.g.
+ * if there are pieces on the columns a, d, e, f, h , the bitmask will be
+ * (binary) 00111001) as the first index, and the position of the rook (0-7
+ * for columns 1-8 (right to left on the mask)) as the second index.
+ *
+ * It returns a row mask appropriate for a rook on the 1st (0 index) row's
+ * attacks; note that the bit at the end of the attack ray will overlap the
+ * first blocking piece (a rook on d-column with rowblock mask 11010011 (note
+ * the 1 in the d-col indicates the rook itself) will get move mask 01101110
+ * (note again the 0 on the d-column; the rook cannot move to itself)).
+ *
+ * Because the return is suitable for a rook on row-1 (0 index), it must be
+ * shifted left by 8*ROW(square) - for example, on the 8th row, the shift by
+ * 8*7 will put it in the MSBs of the uint64_t.
+ */
+uint64_t rowattacks[256][8] = {
+ { U64(0xfe), U64(0xfd), U64(0xfb), U64(0xf7), U64(0xef), U64(0xdf), U64(0xbf), U64(0x7f) }, /* 0x00 */
+ { U64(0xfe), U64(0xfd), U64(0xfb), U64(0xf7), U64(0xef), U64(0xdf), U64(0xbf), U64(0x7f) }, /* 0x01 */
+ { U64(0x02), U64(0xfd), U64(0xfa), U64(0xf6), U64(0xee), U64(0xde), U64(0xbe), U64(0x7e) }, /* 0x02 */
+ { U64(0x02), U64(0xfd), U64(0xfa), U64(0xf6), U64(0xee), U64(0xde), U64(0xbe), U64(0x7e) }, /* 0x03 */
+ { U64(0x06), U64(0x05), U64(0xfb), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x04 */
+ { U64(0x06), U64(0x05), U64(0xfb), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x05 */
+ { U64(0x02), U64(0x05), U64(0xfa), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x06 */
+ { U64(0x02), U64(0x05), U64(0xfa), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x07 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0xf7), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x08 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0xf7), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x09 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0xf6), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x0a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0xf6), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x0b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x0c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x0d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x0e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x0f */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0xef), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x10 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0xef), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x11 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0xee), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x12 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0xee), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x13 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x14 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x15 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x16 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x17 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x18 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x19 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x1a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x1b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x1c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x1d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x1e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x1f */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0xdf), U64(0xa0), U64(0x60) }, /* 0x20 */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0xdf), U64(0xa0), U64(0x60) }, /* 0x21 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0xde), U64(0xa0), U64(0x60) }, /* 0x22 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0xde), U64(0xa0), U64(0x60) }, /* 0x23 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0x24 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0x25 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0x26 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0x27 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x28 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x29 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x2a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x2b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x2c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x2d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x2e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0x2f */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x30 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x31 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x32 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x33 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x34 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x35 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x36 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x37 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x38 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x39 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x3a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x3b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x3c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x3d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x3e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0x3f */
+ { U64(0x7e), U64(0x7d), U64(0x7b), U64(0x77), U64(0x6f), U64(0x5f), U64(0xbf), U64(0x40) }, /* 0x40 */
+ { U64(0x7e), U64(0x7d), U64(0x7b), U64(0x77), U64(0x6f), U64(0x5f), U64(0xbf), U64(0x40) }, /* 0x41 */
+ { U64(0x02), U64(0x7d), U64(0x7a), U64(0x76), U64(0x6e), U64(0x5e), U64(0xbe), U64(0x40) }, /* 0x42 */
+ { U64(0x02), U64(0x7d), U64(0x7a), U64(0x76), U64(0x6e), U64(0x5e), U64(0xbe), U64(0x40) }, /* 0x43 */
+ { U64(0x06), U64(0x05), U64(0x7b), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0x44 */
+ { U64(0x06), U64(0x05), U64(0x7b), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0x45 */
+ { U64(0x02), U64(0x05), U64(0x7a), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0x46 */
+ { U64(0x02), U64(0x05), U64(0x7a), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0x47 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x77), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x48 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x77), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x49 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x76), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x4a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x76), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x4b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x4c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x4d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x4e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0x4f */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x6f), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x50 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x6f), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x51 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x6e), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x52 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x6e), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x53 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x54 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x55 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x56 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x57 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x58 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x59 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x5a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x5b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x5c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x5d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x5e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0x5f */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0x5f), U64(0xa0), U64(0x40) }, /* 0x60 */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0x5f), U64(0xa0), U64(0x40) }, /* 0x61 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0x5e), U64(0xa0), U64(0x40) }, /* 0x62 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0x5e), U64(0xa0), U64(0x40) }, /* 0x63 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0x64 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0x65 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0x66 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0x67 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x68 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x69 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x6a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x6b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x6c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x6d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x6e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0x6f */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x70 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x71 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x72 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x73 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x74 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x75 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x76 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x77 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x78 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x79 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x7a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x7b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x7c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x7d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x7e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0x7f */
+ { U64(0xfe), U64(0xfd), U64(0xfb), U64(0xf7), U64(0xef), U64(0xdf), U64(0xbf), U64(0x7f) }, /* 0x80 */
+ { U64(0xfe), U64(0xfd), U64(0xfb), U64(0xf7), U64(0xef), U64(0xdf), U64(0xbf), U64(0x7f) }, /* 0x81 */
+ { U64(0x02), U64(0xfd), U64(0xfa), U64(0xf6), U64(0xee), U64(0xde), U64(0xbe), U64(0x7e) }, /* 0x82 */
+ { U64(0x02), U64(0xfd), U64(0xfa), U64(0xf6), U64(0xee), U64(0xde), U64(0xbe), U64(0x7e) }, /* 0x83 */
+ { U64(0x06), U64(0x05), U64(0xfb), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x84 */
+ { U64(0x06), U64(0x05), U64(0xfb), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x85 */
+ { U64(0x02), U64(0x05), U64(0xfa), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x86 */
+ { U64(0x02), U64(0x05), U64(0xfa), U64(0xf4), U64(0xec), U64(0xdc), U64(0xbc), U64(0x7c) }, /* 0x87 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0xf7), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x88 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0xf7), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x89 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0xf6), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x8a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0xf6), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x8b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x8c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x8d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x8e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0xf4), U64(0xe8), U64(0xd8), U64(0xb8), U64(0x78) }, /* 0x8f */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0xef), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x90 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0xef), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x91 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0xee), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x92 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0xee), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x93 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x94 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x95 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x96 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0xec), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x97 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x98 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x99 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x9a */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x9b */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x9c */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x9d */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x9e */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0xe8), U64(0xd0), U64(0xb0), U64(0x70) }, /* 0x9f */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0xdf), U64(0xa0), U64(0x60) }, /* 0xa0 */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0xdf), U64(0xa0), U64(0x60) }, /* 0xa1 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0xde), U64(0xa0), U64(0x60) }, /* 0xa2 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0xde), U64(0xa0), U64(0x60) }, /* 0xa3 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0xa4 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0xa5 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0xa6 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0xdc), U64(0xa0), U64(0x60) }, /* 0xa7 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xa8 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xa9 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xaa */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xab */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xac */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xad */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xae */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0xd8), U64(0xa0), U64(0x60) }, /* 0xaf */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb0 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb1 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb2 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb3 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb4 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb5 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb6 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb7 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb8 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xb9 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xba */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xbb */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xbc */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xbd */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xbe */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0xd0), U64(0xa0), U64(0x60) }, /* 0xbf */
+ { U64(0x7e), U64(0x7d), U64(0x7b), U64(0x77), U64(0x6f), U64(0x5f), U64(0xbf), U64(0x40) }, /* 0xc0 */
+ { U64(0x7e), U64(0x7d), U64(0x7b), U64(0x77), U64(0x6f), U64(0x5f), U64(0xbf), U64(0x40) }, /* 0xc1 */
+ { U64(0x02), U64(0x7d), U64(0x7a), U64(0x76), U64(0x6e), U64(0x5e), U64(0xbe), U64(0x40) }, /* 0xc2 */
+ { U64(0x02), U64(0x7d), U64(0x7a), U64(0x76), U64(0x6e), U64(0x5e), U64(0xbe), U64(0x40) }, /* 0xc3 */
+ { U64(0x06), U64(0x05), U64(0x7b), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0xc4 */
+ { U64(0x06), U64(0x05), U64(0x7b), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0xc5 */
+ { U64(0x02), U64(0x05), U64(0x7a), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0xc6 */
+ { U64(0x02), U64(0x05), U64(0x7a), U64(0x74), U64(0x6c), U64(0x5c), U64(0xbc), U64(0x40) }, /* 0xc7 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x77), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xc8 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x77), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xc9 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x76), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xca */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x76), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xcb */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xcc */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xcd */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xce */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x74), U64(0x68), U64(0x58), U64(0xb8), U64(0x40) }, /* 0xcf */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x6f), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd0 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x6f), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd1 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x6e), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd2 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x6e), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd3 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd4 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd5 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd6 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x6c), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd7 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd8 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xd9 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xda */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xdb */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xdc */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xdd */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xde */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x68), U64(0x50), U64(0xb0), U64(0x40) }, /* 0xdf */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0x5f), U64(0xa0), U64(0x40) }, /* 0xe0 */
+ { U64(0x3e), U64(0x3d), U64(0x3b), U64(0x37), U64(0x2f), U64(0x5f), U64(0xa0), U64(0x40) }, /* 0xe1 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0x5e), U64(0xa0), U64(0x40) }, /* 0xe2 */
+ { U64(0x02), U64(0x3d), U64(0x3a), U64(0x36), U64(0x2e), U64(0x5e), U64(0xa0), U64(0x40) }, /* 0xe3 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0xe4 */
+ { U64(0x06), U64(0x05), U64(0x3b), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0xe5 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0xe6 */
+ { U64(0x02), U64(0x05), U64(0x3a), U64(0x34), U64(0x2c), U64(0x5c), U64(0xa0), U64(0x40) }, /* 0xe7 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xe8 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x37), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xe9 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xea */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x36), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xeb */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xec */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xed */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xee */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x34), U64(0x28), U64(0x58), U64(0xa0), U64(0x40) }, /* 0xef */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf0 */
+ { U64(0x1e), U64(0x1d), U64(0x1b), U64(0x17), U64(0x2f), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf1 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf2 */
+ { U64(0x02), U64(0x1d), U64(0x1a), U64(0x16), U64(0x2e), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf3 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf4 */
+ { U64(0x06), U64(0x05), U64(0x1b), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf5 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf6 */
+ { U64(0x02), U64(0x05), U64(0x1a), U64(0x14), U64(0x2c), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf7 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf8 */
+ { U64(0x0e), U64(0x0d), U64(0x0b), U64(0x17), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xf9 */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xfa */
+ { U64(0x02), U64(0x0d), U64(0x0a), U64(0x16), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xfb */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xfc */
+ { U64(0x06), U64(0x05), U64(0x0b), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xfd */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) }, /* 0xfe */
+ { U64(0x02), U64(0x05), U64(0x0a), U64(0x14), U64(0x28), U64(0x50), U64(0xa0), U64(0x40) } /* 0xff */
+};
+
+
+/****************************************************************************
+ * For rook attacks along a column. Using the 'occupied' status of the column
+ * passed in from the rot90 bitboard, shifted to the 8 least-significant bits
+ * (a-column), returns a NON-ROTATED bitmask of attacks for the a-column. You
+ * will want to shift this result over by COL(square) bits to get it in the
+ * right place - think about the way the bitboard works; each row is a byte
+ * (major index, times 8), and each column is a bit (minor index, times 1).
+ * You will want to use whatever ROW the piece is on in a normal bitboard as
+ * the second index.
+ ****************************************************************************/
+
+uint64_t colattacks[256][8] = {
+ { U64(0x0101010101010100), U64(0x0101010101010001), U64(0x0101010101000101), U64(0x0101010100010101), U64(0x0101010001010101), U64(0x0101000101010101), U64(0x0100010101010101), U64(0x0001010101010101) }, /* 0x00 */
+ { U64(0x0101010101010100), U64(0x0101010101010001), U64(0x0101010101000101), U64(0x0101010100010101), U64(0x0101010001010101), U64(0x0101000101010101), U64(0x0100010101010101), U64(0x0001010101010101) }, /* 0x01 */
+ { U64(0x0000000000000100), U64(0x0101010101010001), U64(0x0101010101000100), U64(0x0101010100010100), U64(0x0101010001010100), U64(0x0101000101010100), U64(0x0100010101010100), U64(0x0001010101010100) }, /* 0x02 */
+ { U64(0x0000000000000100), U64(0x0101010101010001), U64(0x0101010101000100), U64(0x0101010100010100), U64(0x0101010001010100), U64(0x0101000101010100), U64(0x0100010101010100), U64(0x0001010101010100) }, /* 0x03 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0101010101000101), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x04 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0101010101000101), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x05 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0101010101000100), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x06 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0101010101000100), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x07 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0101010100010101), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x08 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0101010100010101), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x09 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0101010100010100), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x0a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0101010100010100), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x0b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x0c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x0d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x0e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x0f */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0101010001010101), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x10 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0101010001010101), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x11 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0101010001010100), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x12 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0101010001010100), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x13 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x14 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x15 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x16 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x17 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x18 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x19 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x1a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x1b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x1c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x1d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x1e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x1f */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0101000101010101), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x20 */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0101000101010101), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x21 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0101000101010100), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x22 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0101000101010100), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x23 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x24 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x25 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x26 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x27 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x28 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x29 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x2a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x2b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x2c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x2d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x2e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x2f */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x30 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x31 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x32 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x33 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x34 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x35 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x36 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x37 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x38 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x39 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x3a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x3b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x3c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x3d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x3e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0x3f */
+ { U64(0x0001010101010100), U64(0x0001010101010001), U64(0x0001010101000101), U64(0x0001010100010101), U64(0x0001010001010101), U64(0x0001000101010101), U64(0x0100010101010101), U64(0x0001000000000000) }, /* 0x40 */
+ { U64(0x0001010101010100), U64(0x0001010101010001), U64(0x0001010101000101), U64(0x0001010100010101), U64(0x0001010001010101), U64(0x0001000101010101), U64(0x0100010101010101), U64(0x0001000000000000) }, /* 0x41 */
+ { U64(0x0000000000000100), U64(0x0001010101010001), U64(0x0001010101000100), U64(0x0001010100010100), U64(0x0001010001010100), U64(0x0001000101010100), U64(0x0100010101010100), U64(0x0001000000000000) }, /* 0x42 */
+ { U64(0x0000000000000100), U64(0x0001010101010001), U64(0x0001010101000100), U64(0x0001010100010100), U64(0x0001010001010100), U64(0x0001000101010100), U64(0x0100010101010100), U64(0x0001000000000000) }, /* 0x43 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0001010101000101), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0x44 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0001010101000101), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0x45 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0001010101000100), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0x46 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0001010101000100), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0x47 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0001010100010101), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x48 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0001010100010101), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x49 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0001010100010100), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x4a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0001010100010100), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x4b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x4c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x4d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x4e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0x4f */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0001010001010101), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x50 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0001010001010101), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x51 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0001010001010100), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x52 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0001010001010100), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x53 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x54 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x55 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x56 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x57 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x58 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x59 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x5a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x5b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x5c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x5d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x5e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0x5f */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0001000101010101), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x60 */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0001000101010101), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x61 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0001000101010100), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x62 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0001000101010100), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x63 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x64 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x65 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x66 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x67 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x68 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x69 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x6a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x6b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x6c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x6d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x6e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x6f */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x70 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x71 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x72 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x73 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x74 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x75 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x76 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x77 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x78 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x79 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x7a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x7b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x7c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x7d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x7e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0x7f */
+ { U64(0x0101010101010100), U64(0x0101010101010001), U64(0x0101010101000101), U64(0x0101010100010101), U64(0x0101010001010101), U64(0x0101000101010101), U64(0x0100010101010101), U64(0x0001010101010101) }, /* 0x80 */
+ { U64(0x0101010101010100), U64(0x0101010101010001), U64(0x0101010101000101), U64(0x0101010100010101), U64(0x0101010001010101), U64(0x0101000101010101), U64(0x0100010101010101), U64(0x0001010101010101) }, /* 0x81 */
+ { U64(0x0000000000000100), U64(0x0101010101010001), U64(0x0101010101000100), U64(0x0101010100010100), U64(0x0101010001010100), U64(0x0101000101010100), U64(0x0100010101010100), U64(0x0001010101010100) }, /* 0x82 */
+ { U64(0x0000000000000100), U64(0x0101010101010001), U64(0x0101010101000100), U64(0x0101010100010100), U64(0x0101010001010100), U64(0x0101000101010100), U64(0x0100010101010100), U64(0x0001010101010100) }, /* 0x83 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0101010101000101), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x84 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0101010101000101), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x85 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0101010101000100), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x86 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0101010101000100), U64(0x0101010100010000), U64(0x0101010001010000), U64(0x0101000101010000), U64(0x0100010101010000), U64(0x0001010101010000) }, /* 0x87 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0101010100010101), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x88 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0101010100010101), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x89 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0101010100010100), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x8a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0101010100010100), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x8b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x8c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x8d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x8e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0101010100010000), U64(0x0101010001000000), U64(0x0101000101000000), U64(0x0100010101000000), U64(0x0001010101000000) }, /* 0x8f */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0101010001010101), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x90 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0101010001010101), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x91 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0101010001010100), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x92 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0101010001010100), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x93 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x94 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x95 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x96 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0101010001010000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x97 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x98 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x99 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x9a */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x9b */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x9c */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x9d */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x9e */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0101010001000000), U64(0x0101000100000000), U64(0x0100010100000000), U64(0x0001010100000000) }, /* 0x9f */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0101000101010101), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa0 */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0101000101010101), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa1 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0101000101010100), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa2 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0101000101010100), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa3 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa4 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa5 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa6 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0101000101010000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa7 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa8 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xa9 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xaa */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xab */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xac */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xad */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xae */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0101000101000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xaf */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb0 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb1 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb2 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb3 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb4 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb5 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb6 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb7 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb8 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xb9 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xba */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xbb */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xbc */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xbd */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xbe */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0101000100000000), U64(0x0100010000000000), U64(0x0001010000000000) }, /* 0xbf */
+ { U64(0x0001010101010100), U64(0x0001010101010001), U64(0x0001010101000101), U64(0x0001010100010101), U64(0x0001010001010101), U64(0x0001000101010101), U64(0x0100010101010101), U64(0x0001000000000000) }, /* 0xc0 */
+ { U64(0x0001010101010100), U64(0x0001010101010001), U64(0x0001010101000101), U64(0x0001010100010101), U64(0x0001010001010101), U64(0x0001000101010101), U64(0x0100010101010101), U64(0x0001000000000000) }, /* 0xc1 */
+ { U64(0x0000000000000100), U64(0x0001010101010001), U64(0x0001010101000100), U64(0x0001010100010100), U64(0x0001010001010100), U64(0x0001000101010100), U64(0x0100010101010100), U64(0x0001000000000000) }, /* 0xc2 */
+ { U64(0x0000000000000100), U64(0x0001010101010001), U64(0x0001010101000100), U64(0x0001010100010100), U64(0x0001010001010100), U64(0x0001000101010100), U64(0x0100010101010100), U64(0x0001000000000000) }, /* 0xc3 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0001010101000101), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0xc4 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0001010101000101), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0xc5 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0001010101000100), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0xc6 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0001010101000100), U64(0x0001010100010000), U64(0x0001010001010000), U64(0x0001000101010000), U64(0x0100010101010000), U64(0x0001000000000000) }, /* 0xc7 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0001010100010101), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xc8 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0001010100010101), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xc9 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0001010100010100), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xca */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0001010100010100), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xcb */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xcc */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xcd */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xce */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0001010100010000), U64(0x0001010001000000), U64(0x0001000101000000), U64(0x0100010101000000), U64(0x0001000000000000) }, /* 0xcf */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0001010001010101), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd0 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0001010001010101), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd1 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0001010001010100), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd2 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0001010001010100), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd3 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd4 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd5 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd6 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0001010001010000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd7 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd8 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xd9 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xda */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xdb */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xdc */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xdd */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xde */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0001010001000000), U64(0x0001000100000000), U64(0x0100010100000000), U64(0x0001000000000000) }, /* 0xdf */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0001000101010101), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe0 */
+ { U64(0x0000010101010100), U64(0x0000010101010001), U64(0x0000010101000101), U64(0x0000010100010101), U64(0x0000010001010101), U64(0x0001000101010101), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe1 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0001000101010100), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe2 */
+ { U64(0x0000000000000100), U64(0x0000010101010001), U64(0x0000010101000100), U64(0x0000010100010100), U64(0x0000010001010100), U64(0x0001000101010100), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe3 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe4 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000010101000101), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe5 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe6 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000010101000100), U64(0x0000010100010000), U64(0x0000010001010000), U64(0x0001000101010000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe7 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe8 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000010100010101), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xe9 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xea */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000010100010100), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xeb */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xec */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xed */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xee */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000010100010000), U64(0x0000010001000000), U64(0x0001000101000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xef */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf0 */
+ { U64(0x0000000101010100), U64(0x0000000101010001), U64(0x0000000101000101), U64(0x0000000100010101), U64(0x0000010001010101), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf1 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf2 */
+ { U64(0x0000000000000100), U64(0x0000000101010001), U64(0x0000000101000100), U64(0x0000000100010100), U64(0x0000010001010100), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf3 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf4 */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000101000101), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf5 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf6 */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000101000100), U64(0x0000000100010000), U64(0x0000010001010000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf7 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf8 */
+ { U64(0x0000000001010100), U64(0x0000000001010001), U64(0x0000000001000101), U64(0x0000000100010101), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xf9 */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xfa */
+ { U64(0x0000000000000100), U64(0x0000000001010001), U64(0x0000000001000100), U64(0x0000000100010100), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xfb */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xfc */
+ { U64(0x0000000000010100), U64(0x0000000000010001), U64(0x0000000001000101), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xfd */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) }, /* 0xfe */
+ { U64(0x0000000000000100), U64(0x0000000000010001), U64(0x0000000001000100), U64(0x0000000100010000), U64(0x0000010001000000), U64(0x0001000100000000), U64(0x0100010000000000), U64(0x0001000000000000) } /* 0xff */
+};
+
+/****************************************************************************
+ * For bishop attacks along a diagonal parallel to a8-h1 (rot45). This is
+ * kind of special, because each diagonal is a different length you need to
+ * think carefully about how the shifting works. This will give the move mask
+ * for a bishop on the a8-h1 diagonal (the longest one) in NON-ROTATED format.
+ *
+ * Think carefully about how you want to shift. When you get the result back,
+ * you will want to shift it forward or backward exactly 8 times N, where N is
+ * the number of diagonals the one your bishop is on is away from a8-h1 (a
+ * bishop on a8-h1 will be shifted 0. For a bishop on a7-g1 you will shift
+ * RIGHT by 8 bits; a6-f1 RIGHT by 16 bits, a1-a1 RIGHT by 56 bits. On the
+ * other hand, for a bishop on b8-h2 you will shift LEFT 8 bits, c8-h3 LEFT by
+ * 16 bits, h8-h8 LEFT by 56 bits.
+ *
+ * The other important thing to consider is how you go into the table. Because
+ * the diagonals are not all the same length, you need to aligh one edge of
+ * your diagonal to either the 0 index OR the other edge to the 7 index. The
+ * way you want to do it is if your diagonal touches the left side of the
+ * board (aX-x1), shift so the square on the a-file is in the 0th index; if
+ * your diagonal touches the right side (x8-hX), shift so the square on the
+ * h-file will be in the 7th index. Either way, this means there will be some
+ * garbage not related to your diagonal in the remaining slots - it will
+ * affect the resulting move mask, but when you bitshift it (according to the
+ * previous paragraph) the nonrelevant squares in the mask will overflow out.
+ *
+ * To get a piece's position on the diagonal (the second index in the array),
+ * we consider alignment described above, and realize that because essentially
+ * we're projecting the diagonal down to the first (0-index) row, plus some
+ * garbage, the position index is simply the column the piece is on!
+ ****************************************************************************/
+
+/* Use these to get the number used to index into the next few arrays. Indexed
+ * by square (A1 0, H8 63) for both rotation directions. Use the result from
+ * these arrays as an index into the "shiftamount" arrays following. */
+int rot45diagindex[64] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 2, 3, 4, 5, 6, 7, 8, 9,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 5, 6, 7, 8, 9, 10, 11, 12,
+ 6, 7, 8, 9, 10, 11, 12, 13,
+ 7, 8, 9, 10, 11, 12, 13, 14
+};
+int rot315diagindex[64] = {
+ 7, 6, 5, 4, 3, 2, 1, 0,
+ 8, 7, 6, 5, 4, 3, 2, 1,
+ 9, 8, 7, 6, 5, 4, 3, 2,
+ 10, 9, 8, 7, 6, 5, 4, 3,
+ 11, 10, 9, 8, 7, 6, 5, 4,
+ 12, 11, 10, 9, 8, 7, 6, 5,
+ 13, 12, 11, 10, 9, 8, 7, 6,
+ 14, 13, 12, 11, 10, 9, 8, 7
+};
+
+/* The amount you want to shift the rotated bitboard by (then mask with 0xFF)
+ * to get the correct index. Index into this with the diagonal's number. For
+ * rot45, you want to align >7 diagonals against the 7th index, with garbage
+ * in the bottom, or <7 diagonals against the 0th index, with garbage in the
+ * top, so that when shifting the garbage goes out of the top/bottom of the
+ * board. For rot315 it's the opposite case - >7 diags get aligned to the 0th
+ * index, and <7 diags aligned to the 7th index; this way, the garbage will
+ * still go out the top/bottom of the board. For the lowest diagonals, this
+ * means we might have to shift backwards. (note: The numbers for aligning to
+ * the top bits are generated by "extending" the row backwards.) */
+int rot45index_shiftamountright[15] = { 0, 1, 3, 6, 10, 15, 21, 28, 35, 41, 46, 50, 53, 55, 56 };
+int rot315index_shiftamountright[15] = { 0, 0, 0, 2, 7, 13, 20, 28, 36, 43, 49, 54, 58, 61, 63 };
+int rot315index_shiftamountleft[15] = { 7, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/* The amount you want to shift the result by. Use the number of the diagonal
+ * (0 for a1-a1, 7 for a8-h1, 14 for h8-h8) to index into these. */
+int rotresult_shiftamountleft[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 8, 16, 24, 32, 40, 48, 56 };
+int rotresult_shiftamountright[15] = { 56, 48, 40, 32, 24, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+uint64_t rot45attacks[256][8] = {
+ { U64(0x0002040810204080), U64(0x0100040810204080), U64(0x0102000810204080), U64(0x0102040010204080), U64(0x0102040800204080), U64(0x0102040810004080), U64(0x0102040810200080), U64(0x0102040810204000) }, /* 0x00 */
+ { U64(0x0002040810204080), U64(0x0100040810204080), U64(0x0102000810204080), U64(0x0102040010204080), U64(0x0102040800204080), U64(0x0102040810004080), U64(0x0102040810200080), U64(0x0102040810204000) }, /* 0x01 */
+ { U64(0x0002000000000000), U64(0x0100040810204080), U64(0x0002000810204080), U64(0x0002040010204080), U64(0x0002040800204080), U64(0x0002040810004080), U64(0x0002040810200080), U64(0x0002040810204000) }, /* 0x02 */
+ { U64(0x0002000000000000), U64(0x0100040810204080), U64(0x0002000810204080), U64(0x0002040010204080), U64(0x0002040800204080), U64(0x0002040810004080), U64(0x0002040810200080), U64(0x0002040810204000) }, /* 0x03 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x04 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x05 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x06 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x07 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x08 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x09 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x0a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x0b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x0c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x0d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x0e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x0f */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x10 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x11 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x12 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x13 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x14 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x15 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x16 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x17 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x18 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x19 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x1a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x1b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x1c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x1d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x1e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x1f */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x20 */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x21 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x22 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x23 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x24 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x25 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x26 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x27 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x28 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x29 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x2a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x2b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x2c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x2d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x2e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x2f */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x30 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x31 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x32 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x33 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x34 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x35 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x36 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x37 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x38 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x39 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x3a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x3b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x3c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x3d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x3e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0x3f */
+ { U64(0x0002040810204000), U64(0x0100040810204000), U64(0x0102000810204000), U64(0x0102040010204000), U64(0x0102040800204000), U64(0x0102040810004000), U64(0x0102040810200080), U64(0x0000000000004000) }, /* 0x40 */
+ { U64(0x0002040810204000), U64(0x0100040810204000), U64(0x0102000810204000), U64(0x0102040010204000), U64(0x0102040800204000), U64(0x0102040810004000), U64(0x0102040810200080), U64(0x0000000000004000) }, /* 0x41 */
+ { U64(0x0002000000000000), U64(0x0100040810204000), U64(0x0002000810204000), U64(0x0002040010204000), U64(0x0002040800204000), U64(0x0002040810004000), U64(0x0002040810200080), U64(0x0000000000004000) }, /* 0x42 */
+ { U64(0x0002000000000000), U64(0x0100040810204000), U64(0x0002000810204000), U64(0x0002040010204000), U64(0x0002040800204000), U64(0x0002040810004000), U64(0x0002040810200080), U64(0x0000000000004000) }, /* 0x43 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0x44 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0x45 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0x46 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0x47 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x48 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x49 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x4a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x4b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x4c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x4d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x4e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0x4f */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x50 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x51 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x52 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x53 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x54 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x55 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x56 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x57 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x58 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x59 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x5a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x5b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x5c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x5d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x5e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0x5f */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x60 */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x61 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x62 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x63 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x64 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x65 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x66 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x67 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x68 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x69 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x6a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x6b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x6c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x6d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x6e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x6f */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x70 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x71 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x72 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x73 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x74 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x75 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x76 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x77 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x78 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x79 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x7a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x7b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x7c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x7d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x7e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0x7f */
+ { U64(0x0002040810204080), U64(0x0100040810204080), U64(0x0102000810204080), U64(0x0102040010204080), U64(0x0102040800204080), U64(0x0102040810004080), U64(0x0102040810200080), U64(0x0102040810204000) }, /* 0x80 */
+ { U64(0x0002040810204080), U64(0x0100040810204080), U64(0x0102000810204080), U64(0x0102040010204080), U64(0x0102040800204080), U64(0x0102040810004080), U64(0x0102040810200080), U64(0x0102040810204000) }, /* 0x81 */
+ { U64(0x0002000000000000), U64(0x0100040810204080), U64(0x0002000810204080), U64(0x0002040010204080), U64(0x0002040800204080), U64(0x0002040810004080), U64(0x0002040810200080), U64(0x0002040810204000) }, /* 0x82 */
+ { U64(0x0002000000000000), U64(0x0100040810204080), U64(0x0002000810204080), U64(0x0002040010204080), U64(0x0002040800204080), U64(0x0002040810004080), U64(0x0002040810200080), U64(0x0002040810204000) }, /* 0x83 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x84 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x85 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x86 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204080), U64(0x0000040010204080), U64(0x0000040800204080), U64(0x0000040810004080), U64(0x0000040810200080), U64(0x0000040810204000) }, /* 0x87 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x88 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x89 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x8a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x8b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x8c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x8d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x8e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204080), U64(0x0000000800204080), U64(0x0000000810004080), U64(0x0000000810200080), U64(0x0000000810204000) }, /* 0x8f */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x90 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x91 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x92 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x93 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x94 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x95 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x96 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x97 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x98 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x99 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x9a */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x9b */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x9c */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x9d */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x9e */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204080), U64(0x0000000010004080), U64(0x0000000010200080), U64(0x0000000010204000) }, /* 0x9f */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa0 */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa1 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa2 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa3 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa4 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa5 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa6 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa7 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa8 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xa9 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xaa */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xab */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xac */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xad */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xae */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xaf */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb0 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb1 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb2 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb3 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb4 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb5 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb6 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb7 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb8 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xb9 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xba */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xbb */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xbc */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xbd */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xbe */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004080), U64(0x0000000000200080), U64(0x0000000000204000) }, /* 0xbf */
+ { U64(0x0002040810204000), U64(0x0100040810204000), U64(0x0102000810204000), U64(0x0102040010204000), U64(0x0102040800204000), U64(0x0102040810004000), U64(0x0102040810200080), U64(0x0000000000004000) }, /* 0xc0 */
+ { U64(0x0002040810204000), U64(0x0100040810204000), U64(0x0102000810204000), U64(0x0102040010204000), U64(0x0102040800204000), U64(0x0102040810004000), U64(0x0102040810200080), U64(0x0000000000004000) }, /* 0xc1 */
+ { U64(0x0002000000000000), U64(0x0100040810204000), U64(0x0002000810204000), U64(0x0002040010204000), U64(0x0002040800204000), U64(0x0002040810004000), U64(0x0002040810200080), U64(0x0000000000004000) }, /* 0xc2 */
+ { U64(0x0002000000000000), U64(0x0100040810204000), U64(0x0002000810204000), U64(0x0002040010204000), U64(0x0002040800204000), U64(0x0002040810004000), U64(0x0002040810200080), U64(0x0000000000004000) }, /* 0xc3 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0xc4 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0xc5 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0xc6 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810204000), U64(0x0000040010204000), U64(0x0000040800204000), U64(0x0000040810004000), U64(0x0000040810200080), U64(0x0000000000004000) }, /* 0xc7 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xc8 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xc9 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xca */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xcb */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xcc */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xcd */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xce */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010204000), U64(0x0000000800204000), U64(0x0000000810004000), U64(0x0000000810200080), U64(0x0000000000004000) }, /* 0xcf */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd0 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd1 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd2 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd3 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd4 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd5 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd6 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd7 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd8 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xd9 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xda */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xdb */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xdc */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xdd */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xde */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800204000), U64(0x0000000010004000), U64(0x0000000010200080), U64(0x0000000000004000) }, /* 0xdf */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe0 */
+ { U64(0x0002040810200000), U64(0x0100040810200000), U64(0x0102000810200000), U64(0x0102040010200000), U64(0x0102040800200000), U64(0x0102040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe1 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe2 */
+ { U64(0x0002000000000000), U64(0x0100040810200000), U64(0x0002000810200000), U64(0x0002040010200000), U64(0x0002040800200000), U64(0x0002040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe3 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe4 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe5 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe6 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810200000), U64(0x0000040010200000), U64(0x0000040800200000), U64(0x0000040810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe7 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe8 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xe9 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xea */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xeb */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xec */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xed */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xee */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010200000), U64(0x0000000800200000), U64(0x0000000810004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xef */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf0 */
+ { U64(0x0002040810000000), U64(0x0100040810000000), U64(0x0102000810000000), U64(0x0102040010000000), U64(0x0102040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf1 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf2 */
+ { U64(0x0002000000000000), U64(0x0100040810000000), U64(0x0002000810000000), U64(0x0002040010000000), U64(0x0002040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf3 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf4 */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf5 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf6 */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000810000000), U64(0x0000040010000000), U64(0x0000040800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf7 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf8 */
+ { U64(0x0002040800000000), U64(0x0100040800000000), U64(0x0102000800000000), U64(0x0102040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xf9 */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xfa */
+ { U64(0x0002000000000000), U64(0x0100040800000000), U64(0x0002000800000000), U64(0x0002040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xfb */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xfc */
+ { U64(0x0002040000000000), U64(0x0100040000000000), U64(0x0102000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xfd */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) }, /* 0xfe */
+ { U64(0x0002000000000000), U64(0x0100040000000000), U64(0x0002000800000000), U64(0x0000040010000000), U64(0x0000000800200000), U64(0x0000000010004000), U64(0x0000000000200080), U64(0x0000000000004000) } /* 0xff */
+};
+
+uint64_t rot315attacks[256][8] = {
+ { U64(0x8040201008040200), U64(0x8040201008040001), U64(0x8040201008000201), U64(0x8040201000040201), U64(0x8040200008040201), U64(0x8040001008040201), U64(0x8000201008040201), U64(0x0040201008040201) }, /* 0x00 */
+ { U64(0x8040201008040200), U64(0x8040201008040001), U64(0x8040201008000201), U64(0x8040201000040201), U64(0x8040200008040201), U64(0x8040001008040201), U64(0x8000201008040201), U64(0x0040201008040201) }, /* 0x01 */
+ { U64(0x0000000000000200), U64(0x8040201008040001), U64(0x8040201008000200), U64(0x8040201000040200), U64(0x8040200008040200), U64(0x8040001008040200), U64(0x8000201008040200), U64(0x0040201008040200) }, /* 0x02 */
+ { U64(0x0000000000000200), U64(0x8040201008040001), U64(0x8040201008000200), U64(0x8040201000040200), U64(0x8040200008040200), U64(0x8040001008040200), U64(0x8000201008040200), U64(0x0040201008040200) }, /* 0x03 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x8040201008000201), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x04 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x8040201008000201), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x05 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x8040201008000200), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x06 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x8040201008000200), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x07 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x8040201000040201), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x08 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x8040201000040201), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x09 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x8040201000040200), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x0a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x8040201000040200), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x0b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x0c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x0d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x0e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x0f */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x8040200008040201), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x10 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x8040200008040201), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x11 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x8040200008040200), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x12 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x8040200008040200), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x13 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x14 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x15 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x16 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x17 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x18 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x19 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x1a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x1b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x1c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x1d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x1e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x1f */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x8040001008040201), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x20 */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x8040001008040201), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x21 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x8040001008040200), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x22 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x8040001008040200), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x23 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x24 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x25 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x26 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x27 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x28 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x29 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x2a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x2b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x2c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x2d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x2e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x2f */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x30 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x31 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x32 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x33 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x34 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x35 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x36 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x37 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x38 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x39 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x3a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x3b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x3c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x3d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x3e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0x3f */
+ { U64(0x0040201008040200), U64(0x0040201008040001), U64(0x0040201008000201), U64(0x0040201000040201), U64(0x0040200008040201), U64(0x0040001008040201), U64(0x8000201008040201), U64(0x0040000000000000) }, /* 0x40 */
+ { U64(0x0040201008040200), U64(0x0040201008040001), U64(0x0040201008000201), U64(0x0040201000040201), U64(0x0040200008040201), U64(0x0040001008040201), U64(0x8000201008040201), U64(0x0040000000000000) }, /* 0x41 */
+ { U64(0x0000000000000200), U64(0x0040201008040001), U64(0x0040201008000200), U64(0x0040201000040200), U64(0x0040200008040200), U64(0x0040001008040200), U64(0x8000201008040200), U64(0x0040000000000000) }, /* 0x42 */
+ { U64(0x0000000000000200), U64(0x0040201008040001), U64(0x0040201008000200), U64(0x0040201000040200), U64(0x0040200008040200), U64(0x0040001008040200), U64(0x8000201008040200), U64(0x0040000000000000) }, /* 0x43 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0040201008000201), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0x44 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0040201008000201), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0x45 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0040201008000200), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0x46 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0040201008000200), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0x47 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0040201000040201), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x48 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0040201000040201), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x49 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0040201000040200), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x4a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0040201000040200), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x4b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x4c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x4d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x4e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0x4f */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0040200008040201), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x50 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0040200008040201), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x51 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0040200008040200), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x52 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0040200008040200), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x53 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x54 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x55 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x56 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x57 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x58 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x59 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x5a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x5b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x5c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x5d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x5e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0x5f */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x0040001008040201), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x60 */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x0040001008040201), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x61 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x0040001008040200), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x62 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x0040001008040200), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x63 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x64 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x65 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x66 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x67 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x68 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x69 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x6a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x6b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x6c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x6d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x6e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x6f */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x70 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x71 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x72 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x73 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x74 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x75 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x76 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x77 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x78 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x79 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x7a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x7b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x7c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x7d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x7e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0x7f */
+ { U64(0x8040201008040200), U64(0x8040201008040001), U64(0x8040201008000201), U64(0x8040201000040201), U64(0x8040200008040201), U64(0x8040001008040201), U64(0x8000201008040201), U64(0x0040201008040201) }, /* 0x80 */
+ { U64(0x8040201008040200), U64(0x8040201008040001), U64(0x8040201008000201), U64(0x8040201000040201), U64(0x8040200008040201), U64(0x8040001008040201), U64(0x8000201008040201), U64(0x0040201008040201) }, /* 0x81 */
+ { U64(0x0000000000000200), U64(0x8040201008040001), U64(0x8040201008000200), U64(0x8040201000040200), U64(0x8040200008040200), U64(0x8040001008040200), U64(0x8000201008040200), U64(0x0040201008040200) }, /* 0x82 */
+ { U64(0x0000000000000200), U64(0x8040201008040001), U64(0x8040201008000200), U64(0x8040201000040200), U64(0x8040200008040200), U64(0x8040001008040200), U64(0x8000201008040200), U64(0x0040201008040200) }, /* 0x83 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x8040201008000201), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x84 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x8040201008000201), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x85 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x8040201008000200), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x86 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x8040201008000200), U64(0x8040201000040000), U64(0x8040200008040000), U64(0x8040001008040000), U64(0x8000201008040000), U64(0x0040201008040000) }, /* 0x87 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x8040201000040201), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x88 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x8040201000040201), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x89 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x8040201000040200), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x8a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x8040201000040200), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x8b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x8c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x8d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x8e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x8040201000040000), U64(0x8040200008000000), U64(0x8040001008000000), U64(0x8000201008000000), U64(0x0040201008000000) }, /* 0x8f */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x8040200008040201), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x90 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x8040200008040201), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x91 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x8040200008040200), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x92 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x8040200008040200), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x93 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x94 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x95 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x96 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x8040200008040000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x97 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x98 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x99 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x9a */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x9b */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x9c */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x9d */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x9e */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x8040200008000000), U64(0x8040001000000000), U64(0x8000201000000000), U64(0x0040201000000000) }, /* 0x9f */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x8040001008040201), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa0 */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x8040001008040201), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa1 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x8040001008040200), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa2 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x8040001008040200), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa3 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa4 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa5 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa6 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x8040001008040000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa7 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa8 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xa9 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xaa */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xab */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xac */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xad */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xae */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x8040001008000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xaf */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb0 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb1 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb2 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb3 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb4 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb5 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb6 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb7 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb8 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xb9 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xba */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xbb */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xbc */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xbd */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xbe */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x8040001000000000), U64(0x8000200000000000), U64(0x0040200000000000) }, /* 0xbf */
+ { U64(0x0040201008040200), U64(0x0040201008040001), U64(0x0040201008000201), U64(0x0040201000040201), U64(0x0040200008040201), U64(0x0040001008040201), U64(0x8000201008040201), U64(0x0040000000000000) }, /* 0xc0 */
+ { U64(0x0040201008040200), U64(0x0040201008040001), U64(0x0040201008000201), U64(0x0040201000040201), U64(0x0040200008040201), U64(0x0040001008040201), U64(0x8000201008040201), U64(0x0040000000000000) }, /* 0xc1 */
+ { U64(0x0000000000000200), U64(0x0040201008040001), U64(0x0040201008000200), U64(0x0040201000040200), U64(0x0040200008040200), U64(0x0040001008040200), U64(0x8000201008040200), U64(0x0040000000000000) }, /* 0xc2 */
+ { U64(0x0000000000000200), U64(0x0040201008040001), U64(0x0040201008000200), U64(0x0040201000040200), U64(0x0040200008040200), U64(0x0040001008040200), U64(0x8000201008040200), U64(0x0040000000000000) }, /* 0xc3 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0040201008000201), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0xc4 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0040201008000201), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0xc5 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0040201008000200), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0xc6 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0040201008000200), U64(0x0040201000040000), U64(0x0040200008040000), U64(0x0040001008040000), U64(0x8000201008040000), U64(0x0040000000000000) }, /* 0xc7 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0040201000040201), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xc8 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0040201000040201), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xc9 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0040201000040200), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xca */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0040201000040200), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xcb */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xcc */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xcd */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xce */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0040201000040000), U64(0x0040200008000000), U64(0x0040001008000000), U64(0x8000201008000000), U64(0x0040000000000000) }, /* 0xcf */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0040200008040201), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd0 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0040200008040201), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd1 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0040200008040200), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd2 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0040200008040200), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd3 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd4 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd5 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd6 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0040200008040000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd7 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd8 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xd9 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xda */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xdb */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xdc */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xdd */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xde */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0040200008000000), U64(0x0040001000000000), U64(0x8000201000000000), U64(0x0040000000000000) }, /* 0xdf */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x0040001008040201), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe0 */
+ { U64(0x0000201008040200), U64(0x0000201008040001), U64(0x0000201008000201), U64(0x0000201000040201), U64(0x0000200008040201), U64(0x0040001008040201), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe1 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x0040001008040200), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe2 */
+ { U64(0x0000000000000200), U64(0x0000201008040001), U64(0x0000201008000200), U64(0x0000201000040200), U64(0x0000200008040200), U64(0x0040001008040200), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe3 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe4 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000201008000201), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe5 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe6 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000201008000200), U64(0x0000201000040000), U64(0x0000200008040000), U64(0x0040001008040000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe7 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe8 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000201000040201), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xe9 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xea */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000201000040200), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xeb */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xec */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xed */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xee */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000201000040000), U64(0x0000200008000000), U64(0x0040001008000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xef */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf0 */
+ { U64(0x0000001008040200), U64(0x0000001008040001), U64(0x0000001008000201), U64(0x0000001000040201), U64(0x0000200008040201), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf1 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf2 */
+ { U64(0x0000000000000200), U64(0x0000001008040001), U64(0x0000001008000200), U64(0x0000001000040200), U64(0x0000200008040200), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf3 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf4 */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000001008000201), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf5 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf6 */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000001008000200), U64(0x0000001000040000), U64(0x0000200008040000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf7 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf8 */
+ { U64(0x0000000008040200), U64(0x0000000008040001), U64(0x0000000008000201), U64(0x0000001000040201), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xf9 */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xfa */
+ { U64(0x0000000000000200), U64(0x0000000008040001), U64(0x0000000008000200), U64(0x0000001000040200), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xfb */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xfc */
+ { U64(0x0000000000040200), U64(0x0000000000040001), U64(0x0000000008000201), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xfd */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) }, /* 0xfe */
+ { U64(0x0000000000000200), U64(0x0000000000040001), U64(0x0000000008000200), U64(0x0000001000040000), U64(0x0000200008000000), U64(0x0040001000000000), U64(0x8000200000000000), U64(0x0040000000000000) } /* 0xff */
+};
+/****************************************************************************
+ * board.c - rotated bitboard library; move generation and board state
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+/* For FEN conversion, and move->string conversion */
+char *piecename[2][6] = {
+ { "P", "N", "B", "R", "Q", "K" },
+ { "p", "n", "b", "r", "q", "k" }
+};
+/* Converts int to string. Better than using malloc for 3-length strings. */
+char *squarename[64] = {
+ "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
+ "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
+ "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
+ "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
+ "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
+ "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
+ "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
+ "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"
+};
+#ifndef BB_SHIFTFLIP /* see board.h */
+/* Get a bitboard with only one bit set, on a specified square */
+bitboard_t bb_square[64] = {
+ BB(0x0000000000000001), BB(0x0000000000000002), BB(0x0000000000000004), BB(0x0000000000000008),
+ BB(0x0000000000000010), BB(0x0000000000000020), BB(0x0000000000000040), BB(0x0000000000000080),
+ BB(0x0000000000000100), BB(0x0000000000000200), BB(0x0000000000000400), BB(0x0000000000000800),
+ BB(0x0000000000001000), BB(0x0000000000002000), BB(0x0000000000004000), BB(0x0000000000008000),
+ BB(0x0000000000010000), BB(0x0000000000020000), BB(0x0000000000040000), BB(0x0000000000080000),
+ BB(0x0000000000100000), BB(0x0000000000200000), BB(0x0000000000400000), BB(0x0000000000800000),
+ BB(0x0000000001000000), BB(0x0000000002000000), BB(0x0000000004000000), BB(0x0000000008000000),
+ BB(0x0000000010000000), BB(0x0000000020000000), BB(0x0000000040000000), BB(0x0000000080000000),
+ BB(0x0000000100000000), BB(0x0000000200000000), BB(0x0000000400000000), BB(0x0000000800000000),
+ BB(0x0000001000000000), BB(0x0000002000000000), BB(0x0000004000000000), BB(0x0000008000000000),
+ BB(0x0000010000000000), BB(0x0000020000000000), BB(0x0000040000000000), BB(0x0000080000000000),
+ BB(0x0000100000000000), BB(0x0000200000000000), BB(0x0000400000000000), BB(0x0000800000000000),
+ BB(0x0001000000000000), BB(0x0002000000000000), BB(0x0004000000000000), BB(0x0008000000000000),
+ BB(0x0010000000000000), BB(0x0020000000000000), BB(0x0040000000000000), BB(0x0080000000000000),
+ BB(0x0100000000000000), BB(0x0200000000000000), BB(0x0400000000000000), BB(0x0800000000000000),
+ BB(0x1000000000000000), BB(0x2000000000000000), BB(0x4000000000000000), BB(0x8000000000000000),
+};
+/* The bitwise negation of SINGLESQUARE(x) */
+bitboard_t bb_allexcept[64] = {
+ BB(0xfffffffffffffffe), BB(0xfffffffffffffffd), BB(0xfffffffffffffffb), BB(0xfffffffffffffff7),
+ BB(0xffffffffffffffef), BB(0xffffffffffffffdf), BB(0xffffffffffffffbf), BB(0xffffffffffffff7f),
+ BB(0xfffffffffffffeff), BB(0xfffffffffffffdff), BB(0xfffffffffffffbff), BB(0xfffffffffffff7ff),
+ BB(0xffffffffffffefff), BB(0xffffffffffffdfff), BB(0xffffffffffffbfff), BB(0xffffffffffff7fff),
+ BB(0xfffffffffffeffff), BB(0xfffffffffffdffff), BB(0xfffffffffffbffff), BB(0xfffffffffff7ffff),
+ BB(0xffffffffffefffff), BB(0xffffffffffdfffff), BB(0xffffffffffbfffff), BB(0xffffffffff7fffff),
+ BB(0xfffffffffeffffff), BB(0xfffffffffdffffff), BB(0xfffffffffbffffff), BB(0xfffffffff7ffffff),
+ BB(0xffffffffefffffff), BB(0xffffffffdfffffff), BB(0xffffffffbfffffff), BB(0xffffffff7fffffff),
+ BB(0xfffffffeffffffff), BB(0xfffffffdffffffff), BB(0xfffffffbffffffff), BB(0xfffffff7ffffffff),
+ BB(0xffffffefffffffff), BB(0xffffffdfffffffff), BB(0xffffffbfffffffff), BB(0xffffff7fffffffff),
+ BB(0xfffffeffffffffff), BB(0xfffffdffffffffff), BB(0xfffffbffffffffff), BB(0xfffff7ffffffffff),
+ BB(0xffffefffffffffff), BB(0xffffdfffffffffff), BB(0xffffbfffffffffff), BB(0xffff7fffffffffff),
+ BB(0xfffeffffffffffff), BB(0xfffdffffffffffff), BB(0xfffbffffffffffff), BB(0xfff7ffffffffffff),
+ BB(0xffefffffffffffff), BB(0xffdfffffffffffff), BB(0xffbfffffffffffff), BB(0xff7fffffffffffff),
+ BB(0xfeffffffffffffff), BB(0xfdffffffffffffff), BB(0xfbffffffffffffff), BB(0xf7ffffffffffffff),
+ BB(0xefffffffffffffff), BB(0xdfffffffffffffff), BB(0xbfffffffffffffff), BB(0x7fffffffffffffff),
+};
+#endif
+
+/* Which squares must be unoccupied for COLOR (1st) to castle on SIDE (2nd) */
+static bitboard_t castle_clearsquares[2][2] = {
+ /* queenside kingside */
+ { BB(0x000000000000000e), BB(0x0000000000000060) }, /* white */
+ { BB(0x0e00000000000000), BB(0x6000000000000000) } /* black */
+};
+/* Which squares must be unthreatened for COLOR to castle on SIDE */
+static bitboard_t castle_safesquares[2][2] = {
+ /* queenside kingside */
+ { BB(0x000000000000001c), BB(0x0000000000000070) }, /* white */
+ { BB(0x1c00000000000000), BB(0x7000000000000000) } /* black */
+};
+/* A mask for the cols adjacent to a given col - for pawn captures, AND with a
+ * row-mask for the rank you need the pawns to be on */
+bitboard_t bb_adjacentcols[8] = {
+ BB_FILEB,
+ BB_FILEA | BB_FILEC,
+ BB_FILEB | BB_FILED,
+ BB_FILEC | BB_FILEE,
+ BB_FILED | BB_FILEF,
+ BB_FILEE | BB_FILEG,
+ BB_FILEF | BB_FILEH,
+ BB_FILEG
+};
+/* used for determining when a pawn is passed */
+bitboard_t bb_passedpawnmask[2][64] = {
+ /* WHITE */
+ {
+ BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000),
+ BB(0x0303030303030000), BB(0x0707070707070000), BB(0x0e0e0e0e0e0e0000), BB(0x1c1c1c1c1c1c0000), BB(0x3838383838380000), BB(0x7070707070700000), BB(0xe0e0e0e0e0e00000), BB(0xc0c0c0c0c0c00000),
+ BB(0x0303030303000000), BB(0x0707070707000000), BB(0x0e0e0e0e0e000000), BB(0x1c1c1c1c1c000000), BB(0x3838383838000000), BB(0x7070707070000000), BB(0xe0e0e0e0e0000000), BB(0xc0c0c0c0c0000000),
+ BB(0x0303030300000000), BB(0x0707070700000000), BB(0x0e0e0e0e00000000), BB(0x1c1c1c1c00000000), BB(0x3838383800000000), BB(0x7070707000000000), BB(0xe0e0e0e000000000), BB(0xc0c0c0c000000000),
+ BB(0x0303030000000000), BB(0x0707070000000000), BB(0x0e0e0e0000000000), BB(0x1c1c1c0000000000), BB(0x3838380000000000), BB(0x7070700000000000), BB(0xe0e0e00000000000), BB(0xc0c0c00000000000),
+ BB(0x0303000000000000), BB(0x0707000000000000), BB(0x0e0e000000000000), BB(0x1c1c000000000000), BB(0x3838000000000000), BB(0x7070000000000000), BB(0xe0e0000000000000), BB(0xc0c0000000000000),
+ BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000),
+ BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000)
+ },
+ /* BLACK */
+ {
+ BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000),
+ BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000),
+ BB(0x0000000000000303), BB(0x0000000000000707), BB(0x0000000000000e0e), BB(0x0000000000001c1c), BB(0x0000000000003838), BB(0x0000000000007070), BB(0x000000000000e0e0), BB(0x000000000000c0c0),
+ BB(0x0000000000030303), BB(0x0000000000070707), BB(0x00000000000e0e0e), BB(0x00000000001c1c1c), BB(0x0000000000383838), BB(0x0000000000707070), BB(0x0000000000e0e0e0), BB(0x0000000000c0c0c0),
+ BB(0x0000000003030303), BB(0x0000000007070707), BB(0x000000000e0e0e0e), BB(0x000000001c1c1c1c), BB(0x0000000038383838), BB(0x0000000070707070), BB(0x00000000e0e0e0e0), BB(0x00000000c0c0c0c0),
+ BB(0x0000000303030303), BB(0x0000000707070707), BB(0x0000000e0e0e0e0e), BB(0x0000001c1c1c1c1c), BB(0x0000003838383838), BB(0x0000007070707070), BB(0x000000e0e0e0e0e0), BB(0x000000c0c0c0c0c0),
+ BB(0x0000030303030303), BB(0x0000070707070707), BB(0x00000e0e0e0e0e0e), BB(0x00001c1c1c1c1c1c), BB(0x0000383838383838), BB(0x0000707070707070), BB(0x0000e0e0e0e0e0e0), BB(0x0000c0c0c0c0c0c0),
+ BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000), BB(0x0000000000000000)
+ }
+};
+
+/* Rotation translation from normal-oriented square indices to square indices
+ * suitable for setting bits on board_t->occupied{90,45,315}. Note that we
+ * don't use these for move generation at all, just for setting/clearing bits
+ * on the occupied boards. */
+#define ROT90SQUAREINDEX(s) rot90squareindex[s] /*(SQUARE(ROW(s),COL(s))) - slower*/
+static int rot90squareindex[64] = {
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 1, 9, 17, 25, 33, 41, 49, 57,
+ 2, 10, 18, 26, 34, 42, 50, 58,
+ 3, 11, 19, 27, 35, 43, 51, 59,
+ 4, 12, 20, 28, 36, 44, 52, 60,
+ 5, 13, 21, 29, 37, 45, 53, 61,
+ 6, 14, 22, 30, 38, 46, 54, 62,
+ 7, 15, 23, 31, 39, 47, 55, 63
+};
+#define ROT45SQUAREINDEX(s) rot45squareindex[s]
+static int rot45squareindex[64] = {
+ 0, 2, 5, 9, 14, 20, 27, 35,
+ 1, 4, 8, 13, 19, 26, 34, 42,
+ 3, 7, 12, 18, 25, 33, 41, 48,
+ 6, 11, 17, 24, 32, 40, 47, 53,
+ 10, 16, 23, 31, 39, 46, 52, 57,
+ 15, 22, 30, 38, 45, 51, 56, 60,
+ 21, 29, 37, 44, 50, 55, 59, 62,
+ 28, 36, 43, 49, 54, 58, 61, 63
+};
+#define ROT315SQUAREINDEX(s) rot315squareindex[s]
+static int rot315squareindex[64] = {
+ 28, 21, 15, 10, 6, 3, 1, 0,
+ 36, 29, 22, 16, 11, 7, 4, 2,
+ 43, 37, 30, 23, 17, 12, 8, 5,
+ 49, 44, 38, 31, 24, 18, 13, 9,
+ 54, 50, 45, 39, 32, 25, 19, 14,
+ 58, 55, 51, 46, 40, 33, 26, 20,
+ 61, 59, 56, 52, 47, 41, 34, 27,
+ 63, 62, 60, 57, 53, 48, 42, 35,
+};
+
+/* for material count */
+extern int16_t eval_piecevalue[6];
+
+
+
+#define ZOBRIST_DEFAULT_HASH 0
+/* Table of random numbers used to generate the zobrist hash. The indices are
+ * first the color (WHITE/BLACK), then the piece type (PAWN-KING), then the
+ * square the piece is on (A1-H8) */
+zobrist_t zobrist_piece[2][6][64];
+/* Whose move is it (WHITE/BLACK)? The value present if white has the move. */
+zobrist_t zobrist_tomove;
+/* Which square (A1-H8) is the enpassant square? If enpassant is not possible,
+ * use the key at index 0. */
+zobrist_t zobrist_ep[64];
+/* Can (WHITE/BLACK, first) castle on the (KINGSIDE/QUEENSIDE, second)? If so,
+ * the value here is xored into the hash. */
+zobrist_t zobrist_castle[2][2];
+/* Have the arrays been initialized? If you reinitialize them in the middle of
+ * play, the keys will get screwed up. */
+char zobrist_initialized = 0;
+
+/**
+ * Initialize the zobrist tables.
+ */
+void init_zobrist()
+{
+ int i, j, k;
+
+ /* just in case... */
+ if (zobrist_initialized)
+ {
+ return;
+ }
+
+ /* Init the piece position array */
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 6; j++)
+ {
+ for (k = 0; k < 64; k++)
+ {
+ zobrist_piece[i][j][k] = (zobrist_t)rand64();
+ }
+ }
+ }
+
+ /* Init the whose-move-is-it value */
+ zobrist_tomove = (zobrist_t)rand64();
+
+ /* Init the enpassant square array */
+ for (i = 0; i < 64; i++)
+ {
+ zobrist_ep[i] = (zobrist_t)rand64();
+ }
+
+ /* Init the castling rights array */
+ zobrist_castle[0][0] = (zobrist_t)rand64();
+ zobrist_castle[0][1] = (zobrist_t)rand64();
+ zobrist_castle[1][0] = (zobrist_t)rand64();
+ zobrist_castle[1][1] = (zobrist_t)rand64();
+
+ zobrist_initialized = 1;
+ return;
+}
+
+/**
+ * (Re)generate the zobrist hash for a board, store it in board->hash
+ * This shouldn't be used every time you change the zobrist, only when
+ * initializing the board.
+ */
+void zobrist_gen(board_t *board)
+{
+ unsigned char color;
+ piece_t piece;
+ square_t square;
+
+ int i, j;
+ bitboard_t pos;
+ zobrist_t hash = ZOBRIST_DEFAULT_HASH;
+
+ if (board == NULL)
+ {
+ return;
+ }
+ if (!zobrist_initialized)
+ {
+ init_zobrist();
+ }
+
+ /* XOR in the zobrist for each piece on the board */
+ for (color = 0; color < 2; color++)
+ {
+ for (piece = 0; piece < 6; piece++)
+ {
+ pos = board->pos[color][piece];
+ while (pos)
+ {
+ /* Find the first bit */
+ square = BITSCAN(pos);
+ /* throw in the hash */
+ hash ^= zobrist_piece[color][piece][square];
+ /* and clear the bit */
+ pos &= BB_ALLEXCEPT(square);
+ }
+ }
+ }
+ /* Have the hash reflect special conditions on the board */
+ /* En passant */
+ hash ^= zobrist_ep[board->ep];
+ /* Castling rights */
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ if (board->castle[i][j])
+ {
+ hash ^= zobrist_castle[i][j];
+ }
+ }
+ }
+ /* Who has the move */
+ if (board->tomove == WHITE)
+ {
+ hash ^= zobrist_tomove;
+ }
+
+ board->hash = hash;
+ return;
+}
+
+/****************************************************************************
+ * BITBOARD FUNCTIONS
+ ****************************************************************************/
+static void board_addmoves_pawn(board_t *, square_t, unsigned char, movelist_t *);
+static void board_addmoves_ep(board_t *, unsigned char, movelist_t *);
+static void board_addmoves_king(board_t *, square_t, unsigned char, movelist_t *);
+static void board_addmoves(board_t *, square_t, piece_t, unsigned char, movelist_t *);
+
+static void board_addcaptures_pawn(board_t *, square_t, unsigned char, movelist_t *);
+static void board_addcaptures_king(board_t *, square_t, unsigned char, movelist_t *);
+static void board_addcaptures(board_t *, square_t, piece_t, unsigned char, movelist_t *);
+static void board_togglepiece(board_t *, square_t, unsigned char, piece_t);
+static void board_regeneratethreatened(board_t *);
+
+/**
+ * Generate a fresh board with the default initial starting position.
+ */
+board_t *board_init()
+{
+ board_t *board = malloc(sizeof(board_t));
+ affirm_msg(board, "Couldn't allocate board");
+
+ board->pos[WHITE][PAWN] = BB_RANK2;
+ board->pos[WHITE][KNIGHT] = BB_SQUARE(B1) | BB_SQUARE(G1);
+ board->pos[WHITE][BISHOP] = BB_SQUARE(C1) | BB_SQUARE(F1);
+ board->pos[WHITE][ROOK] = BB_SQUARE(A1) | BB_SQUARE(H1);
+ board->pos[WHITE][QUEEN] = BB_SQUARE(D1);
+ board->pos[WHITE][KING] = BB_SQUARE(E1);
+ board->pos[BLACK][PAWN] = BB_RANK7;
+ board->pos[BLACK][KNIGHT] = BB_SQUARE(B8) | BB_SQUARE(G8);
+ board->pos[BLACK][BISHOP] = BB_SQUARE(C8) | BB_SQUARE(F8);
+ board->pos[BLACK][ROOK] = BB_SQUARE(A8) | BB_SQUARE(H8);
+ board->pos[BLACK][QUEEN] = BB_SQUARE(D8);
+ board->pos[BLACK][KING] = BB_SQUARE(E8);
+
+ board->piecesofcolor[WHITE] = BB_RANK1 | BB_RANK2;
+ board->piecesofcolor[BLACK] = BB_RANK8 | BB_RANK7;
+
+ board->attackedby[WHITE] = BB_RANK3 | BB_RANK2 | (BB_RANK1 ^ BB_SQUARE(A1) ^ BB_SQUARE(H1));
+ board->attackedby[BLACK] = BB_RANK6 | BB_RANK7 | (BB_RANK8 ^ BB_SQUARE(A8) ^ BB_SQUARE(H8));
+
+ board->occupied = BB_RANK1 | BB_RANK2 | BB_RANK7 | BB_RANK8;
+ board->occupied90 = BB_FILEA | BB_FILEB | BB_FILEG | BB_FILEH;
+ /* These ugly numbers, in contrast to the beautifully simple code
+ * above, are in fact correct. Check with ./bbtools/rotvisualizer */
+ board->occupied45 = BB(0xecc61c3c3c386337);
+ board->occupied315 = BB(0xfb31861c38618cdf);
+
+ board->ep = 0;
+ board->castle[WHITE][QUEENSIDE] = 1;
+ board->castle[WHITE][KINGSIDE] = 1;
+ board->castle[BLACK][QUEENSIDE] = 1;
+ board->castle[BLACK][KINGSIDE] = 1;
+ board->hascastled[WHITE] = 0;
+ board->hascastled[BLACK] = 0;
+ board->tomove = WHITE;
+ board->halfmoves = 0;
+ board->moves = 0;
+ board->reps = 0;
+
+ board->material[WHITE] = (8 * eval_piecevalue[PAWN]) +
+ (2 * eval_piecevalue[KNIGHT]) +
+ (2 * eval_piecevalue[BISHOP]) +
+ (2 * eval_piecevalue[ROOK]) +
+ (eval_piecevalue[QUEEN]) +
+ (eval_piecevalue[KING]);
+ board->material[BLACK] = board->material[WHITE];
+
+ zobrist_gen(board);
+
+ return board;
+}
+
+/**
+ * Free all memory associated with a board_t.
+ */
+void board_destroy(board_t *board)
+{
+ if (board)
+ {
+ free(board);
+ }
+}
+
+/**
+ * Generates a FEN string for the given position. Free it yourself when you're
+ * done with it. This function makes no effort to be fast; you shouldn't be
+ * using it during the search process anyway.
+ */
+#define FEN_MAX_LENGTH 85
+char *board_fen(board_t *board)
+{
+ char *fen;
+ int row, col;
+ char emptysquares[] = "0"; /* counts consecutive empty squares */
+ char halfmove[8]; /* Move clock string - "8 45" maybe */
+ piece_t piece;
+ unsigned char color;
+ unsigned char empty_end_of_line;
+
+ if (board == NULL)
+ {
+ return NULL;
+ }
+
+ fen = malloc(FEN_MAX_LENGTH + 1);
+ affirm_msg(fen, "Couldn't allocate board FEN");
+ fen[0] = 0;
+
+ for (row = 7; row >= 0; row--)
+ {
+ emptysquares[0] = '0';
+ empty_end_of_line = 0;
+
+ for (col = 0; col < 8; col++)
+ {
+ color = 0; /* really init'ed next line; this makes gcc happy */
+ piece = board_pieceatsquare(board, SQUARE(col,row), &color);
+ if (piece == (piece_t)-1)
+ {
+ emptysquares[0]++;
+ if (col == 7)
+ {
+ empty_end_of_line = 1;
+ }
+ }
+ else
+ {
+ /* print the emptysquare count if it exists */
+ if (emptysquares[0] != '0')
+ {
+ strcat(fen, emptysquares);
+ emptysquares[0] = '0';
+ }
+ strcat(fen, piecename[color][piece]);
+ }
+ }
+ /* we finished printing this row, unless it was empty */
+ if (empty_end_of_line)
+ {
+ strcat(fen, emptysquares);
+ }
+ /* print the row separator */
+ strcat(fen, ((row > 0) ? "/" : " "));
+ }
+ /* now all that's left is the flags */
+ strcat(fen, ((board->tomove == WHITE) ? "w " : "b "));
+ /* castle privileges - this is kinda messy */
+ if (!(board->castle[WHITE][QUEENSIDE] || board->castle[WHITE][KINGSIDE] ||
+ board->castle[BLACK][QUEENSIDE] || board->castle[BLACK][KINGSIDE]))
+ {
+ strcat(fen, "-");
+ }
+ else
+ {
+ if (board->castle[WHITE][KINGSIDE]) strcat(fen, "K");
+ if (board->castle[WHITE][QUEENSIDE]) strcat(fen, "Q");
+ if (board->castle[BLACK][KINGSIDE]) strcat(fen, "k");
+ if (board->castle[BLACK][QUEENSIDE]) strcat(fen, "q");
+ }
+ strcat(fen, " ");
+ /* enpassant square */
+ strcat(fen, ((board->ep != 0) ? squarename[board->ep] : "-"));
+ strcat(fen, " ");
+ /* move clocks - 0 for absolute move */
+ sprintf(halfmove, "%d %d", board->halfmoves, (board->moves + 1)/2);
+ strcat(fen, halfmove);
+
+ return fen;
+}
+
+/**
+ * Gets the piece at the given square index. If the square is empty, -1.
+ * You should already know that there's a piece there when you call this.
+ * If the board is NULL or the square is invalid, -2.
+ * If the third argument is non-null, stores the color of the piece in there
+ * (unmodified if piece not present).
+ */
+piece_t board_pieceatsquare(board_t *board, square_t square, unsigned char *c)
+{
+ bitboard_t mask;
+ piece_t piece;
+ unsigned char color;
+
+ if (board == NULL || square > 63)
+ {
+ return -2;
+ }
+
+ mask = BB_SQUARE(square);
+
+ /* find what color the piece is */
+ if (board->piecesofcolor[WHITE] & mask)
+ {
+ color = WHITE;
+ }
+ else if (board->piecesofcolor[BLACK] & mask)
+ {
+ color = BLACK;
+ }
+ else
+ {
+ return -1;
+ }
+
+ if (c != NULL)
+ {
+ *c = color;
+ }
+
+ /* find what piece type it is */
+ piece = 0;
+ while (!(board->pos[color][piece] & mask))
+ {
+ piece++;
+ }
+ return piece;
+}
+
+/**
+ * Is the player whose move it is in check? (1 if so, 0 if not)
+ */
+int board_incheck(board_t *board)
+{
+ return board_colorincheck(board, board->tomove);
+}
+
+/**
+ * Is the given player in check? (1 if so, 0 if not)
+ */
+int board_colorincheck(board_t *board, unsigned char color)
+{
+ return !!(board->pos[color][KING] & board->attackedby[OTHERCOLOR(color)]);
+}
+
+/**
+ * Check if the player to move is checkmated or stalemated. Returns either
+ * BOARD_CHECKMATED or BOARD_STALEMATED (from board.h), or 0 if neither.
+ * This is a very expensive call. Only the engine, not the searcher, should
+ * use this in-between moves to determine when the game ends.
+ */
+int board_mated(board_t *board)
+{
+ int result;
+ movelist_t moves;
+ move_t move;
+ unsigned char color;
+
+ color = board->tomove;
+ result = board_colorincheck(board, color) ?
+ BOARD_CHECKMATED : BOARD_STALEMATED;
+ board_generatemoves(board, &moves);
+
+
+ while (!movelist_isempty(&moves))
+ {
+ move = movelist_remove_max(&moves);
+ /* try the move, see if it puts us in check */
+ board_applymove(board, move);
+ if (!board_colorincheck(board, color))
+ {
+ /* found a legal move */
+ board_undomove(board, move);
+ result = 0;
+ break;
+ }
+ board_undomove(board, move);
+ }
+ movelist_destroy(&moves);
+ return result;
+}
+
+/**
+ * Is the pawn of given color at given square passed?
+ */
+int board_pawnpassed(board_t *board, square_t square, unsigned char color)
+{
+ return !(bb_passedpawnmask[color][square] &
+ board->pos[OTHERCOLOR(color)][PAWN]);
+}
+
+/**
+ * Is the given square attacked by any piece of the given color? 1 or 0
+ * Presumably the square has the OTHERCOLOR(color)'s king on it
+ * Note: This is "the" expensive call now that the board library doesn't use
+ * attacked bitboards.
+ */
+int board_squareisattacked(board_t *board, square_t square, unsigned char color)
+{
+ return !!(BB_SQUARE(square) & board->attackedby[color]);
+}
+
+/**
+ * Returns true if *any* of the given squares are attacked by color. Useful
+ * for determining castling legality
+ */
+int board_squaresareattacked(board_t *board, bitboard_t squares, unsigned char color)
+{
+ return !!(squares & board->attackedby[color]);
+}
+
+
+/******************
+ * Move generation
+ ******************/
+
+/**
+ * Given the current board state, returns a bitmask representing all possible
+ * attacks from a given square assuming a piece of the specified type/color at
+ * that square. This is not the same as all the moves the piece at that square
+ * can make - see the special cases: pawns (capture/ep) and kings (castling).
+ * For pawns, forward pushes are NOT reflected in this mask, but diagonally
+ * threatened squares ARE, EVEN IF there is a friendly piece there.
+ *
+ * Note: Considering how the attack bitboards work, realize that we want to
+ * keep both attacks on other color's pieces and attacks on same color's
+ * pieces in here. The board_addmoves functions take care of making sure we
+ * don't capture our own pieces.
+ *
+ * For a cache-friendly optimization, consider taking the slidingpiece's
+ * index OUT of the occupancy mask before looking up - i.e. for 11101011 and
+ * the rook is the 3rd index from the right, use 11100011 as a lookup key
+ * instead, so subsequent accesses with that mask (if you move the rook along
+ * the column/row, etc) stay in cache.
+ * UPDATE: It seems to not help. I took it out.
+ */
+bitboard_t board_attacksfrom(board_t *board, square_t square, piece_t piece, unsigned char color)
+{
+ /* Used for rook/bishop attack generation */
+ int shiftamount;
+ int diag;
+ bitboard_t movemask;
+ bitboard_t rowatk, colatk;
+ bitboard_t diag45attacks, diag315attacks;
+
+ /* NOTE: We mask with ~piecesofcolor in the calling function. */
+ switch (piece)
+ {
+ case PAWN:
+ return pawnattacks[color][square];
+ case KNIGHT:
+ return knightattacks[square];
+ case BISHOP:
+ /* The first table lookup */
+ diag = rot45diagindex[square];
+ movemask = rot45attacks[(board->occupied45 >> rot45index_shiftamountright[diag]) & 0xFF]
+ [COL(square)];
+ diag45attacks = (movemask << rotresult_shiftamountleft[diag])
+ >> rotresult_shiftamountright[diag];
+ /* The second table lookup */
+ diag = rot315diagindex[square];
+ movemask = rot315attacks[((board->occupied315 << rot315index_shiftamountleft[diag]) >> rot315index_shiftamountright[diag]) & 0xFF]
+ [COL(square)];
+ diag315attacks = (movemask << rotresult_shiftamountleft[diag])
+ >> rotresult_shiftamountright[diag];
+ /* Put them together */
+ return (diag45attacks | diag315attacks);
+ case ROOK:
+ /* The first table lookup */
+ shiftamount = 8 * ROW(square);
+ movemask = rowattacks[(board->occupied >> shiftamount) & 0xFF][COL(square)];
+ rowatk = movemask << shiftamount;
+ /* The second table lookup */
+ shiftamount = COL(square);
+ movemask = colattacks[(board->occupied90 >> (shiftamount * 8)) & 0xFF][ROW(square)];
+ colatk = movemask << shiftamount;
+ /* Put them together */
+ return (rowatk | colatk);
+ case QUEEN:
+ return board_attacksfrom(board, square, BISHOP, color) |
+ board_attacksfrom(board, square, ROOK, color);
+ case KING:
+ return kingattacks[square];
+ }
+ /* If we got to here then piece was invalid */
+ panic("Invalid piece!");
+ return BB(0x0);
+}
+
+/**
+ * A bitboard of all legal pawn pushes from a square (in the direction
+ * determined by color) considering the occupied state of the board
+ */
+bitboard_t board_pawnpushesfrom(board_t *board, square_t square, unsigned char color)
+{
+ bitboard_t moves, emptysquares;
+
+ emptysquares = ~(board->occupied);
+ moves = pawnmoves[color][square] & emptysquares; /* can't push if blocked */
+ /* handle double push only if a single push was available */
+ if (moves)
+ {
+ if (color == WHITE)
+ {
+ if (ROW(square) == RANK_2)
+ {
+ moves |= pawnmoves[color][square + 8] & emptysquares;
+ }
+ }
+ else if (ROW(square) == RANK_7)
+ {
+ moves |= pawnmoves[color][square - 8] & emptysquares;
+ }
+ }
+ return moves;
+}
+
+/**
+ * Generates a linkedlist of "legal" moves for the color to play at the given
+ * position. The moves are guaranteed legal, with all appropriate flags set,
+ * suitable for being given to makemove(), EXCEPT it is possible that the move
+ * might leave the player in check. We leave this task to the searcher - since
+ * it is necessary to call makemove() to see if a move leaves the player in
+ * check, and because the searcher calls makemove() anyway; we don't want to
+ * waste time calling it twice.
+ * This list needs to be movelist_destroy()ed. If there are no legal moves,
+ * returns an empty list; if the board is NULL, returns a null pointer.
+ */
+void board_generatemoves(board_t *board, movelist_t *ml)
+{
+ bitboard_t position;
+ piece_t piece;
+ square_t square;
+ unsigned char color;
+
+ assert(board);
+
+ color = board->tomove;
+ movelist_init(ml);
+ /* we only need to do this part once, not once per pawn */
+ if (board->ep)
+ {
+ board_addmoves_ep(board, color, ml);
+ }
+ /* now do the rest of the moves */
+ for (piece = 0; piece < 6; piece++)
+ {
+ position = board->pos[color][piece];
+ while (position)
+ {
+ /* find a piece */
+ square = BITSCAN(position);
+ /* clear the bit */
+ position ^= BB_SQUARE(square);
+ /* special functions for special cases */
+ switch (piece)
+ {
+ case PAWN:
+ board_addmoves_pawn(board, square, color, ml);
+ break;
+ case KING:
+ board_addmoves_king(board, square, color, ml);
+ break;
+ /* for knights, rooks, bishops, queens,
+ * we can use attacksfrom() directly */
+ default:
+ board_addmoves(board, square, piece, color, ml);
+ }
+ }
+ }
+ return;
+}
+
+/**
+ * The board_addmoves* series of functions take pointers to two linkedlists,
+ * and add each legal move for the specified piece of the specified color at
+ * the specified square to the lists, sorted by capture/noncapture.
+ */
+static void board_addmoves_pawn(board_t *board, square_t square, unsigned char color,
+ movelist_t *ml)
+{
+ bitboard_t moves;
+ square_t destsquare;
+ piece_t captpiece;
+ move_t move;
+ /* note enpassant is handled separately. first we do captures: pawns
+ * can't move to a square they threaten unless it's a capture */
+ moves = pawnattacks[color][square] & /* inlined attacksfrom */
+ board->piecesofcolor[OTHERCOLOR(color)];
+ while (moves)
+ {
+ destsquare = BITSCAN(moves);
+ moves ^= BB_SQUARE(destsquare);
+ captpiece = board_pieceatsquare(board, destsquare, NULL);
+ move = (square << MOV_INDEX_SRC) |
+ (destsquare << MOV_INDEX_DEST) |
+ (color << MOV_INDEX_COLOR) |
+ (0x1 << MOV_INDEX_CAPT) |
+ (captpiece << MOV_INDEX_CAPTPC) |
+ (PAWN << MOV_INDEX_PIECE);
+ /* handle promotions */
+ if (ROW(destsquare) == HOMEROW(OTHERCOLOR(color)))
+ {
+ move |= (0x1 << MOV_INDEX_PROM);
+ movelist_add(ml, board->attackedby, (move | (BISHOP << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (ROOK << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (KNIGHT << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (QUEEN << MOV_INDEX_PROMPC)));
+ }
+ else /* normal capture */
+ {
+ movelist_add(ml, board->attackedby, move);
+ }
+ }
+ /* now we handle pushes */
+ moves = board_pawnpushesfrom(board, square, color);
+ /* and now we have the proper movemask generated */
+ while (moves)
+ {
+ destsquare = BITSCAN(moves);
+ moves ^= BB_SQUARE(destsquare);
+ move = (square << MOV_INDEX_SRC) |
+ (destsquare << MOV_INDEX_DEST) |
+ (color << MOV_INDEX_COLOR) |
+ (PAWN << MOV_INDEX_PIECE);
+ /* handle promotions - add to the captures list because pawn
+ * promotions, like captures, change the board's material */
+ if (ROW(destsquare) == HOMEROW(OTHERCOLOR(color)))
+ {
+ move |= (0x1 << MOV_INDEX_PROM);
+ movelist_add(ml, board->attackedby, (move | (BISHOP << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (ROOK << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (KNIGHT << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (QUEEN << MOV_INDEX_PROMPC)));
+ }
+ else /* normal push */
+ {
+ movelist_add(ml, board->attackedby, move);
+ }
+ }
+ /* and we're done, phew */
+ return;
+}
+/* don't call this if board->ep = 0 */
+static void board_addmoves_ep(board_t *board, unsigned char color, movelist_t *ml)
+{
+ bitboard_t pawns;
+ square_t fromsquare; /* we know where the dest is; we need this now */
+ move_t move;
+
+ assert(board->ep);
+
+ /* find all pawns eligible to make the capture */
+ pawns = bb_adjacentcols[COL(board->ep)] & /* the col the pawn is on */
+ BB_EP_FROMRANK(color) & /* the rank a pawn needs to be on */
+ board->pos[color][PAWN] /* where your pawns actually are */;
+ while (pawns)
+ {
+ fromsquare = BITSCAN(pawns);
+ pawns ^= BB_SQUARE(fromsquare);
+ move = (fromsquare << MOV_INDEX_SRC) |
+ (board->ep << MOV_INDEX_DEST) |
+ (0x1 << MOV_INDEX_EP) |
+ (0x1 << MOV_INDEX_CAPT) |
+ (PAWN << MOV_INDEX_CAPTPC) |
+ (PAWN << MOV_INDEX_PIECE);
+ movelist_add(ml, board->attackedby, move);
+ }
+ return;
+}
+/* wrapper for board_addmoves() with a special case handler for castling */
+static void board_addmoves_king(board_t *board, square_t square, unsigned char color,
+ movelist_t *ml)
+{
+ move_t move;
+ square_t destsquare;
+ int side;
+ /* used in the second half */
+ bitboard_t moves, capts;
+ piece_t captpiece;
+
+ /* deal with castling - iterate side={0,1} */
+ for (side = 0; side < 2; side++)
+ {
+ if (board->castle[color][side])
+ {
+ /* If the squares are occupied (1st two lines) or
+ * threatened (2nd two) then we cannot castle */
+ if (!((castle_clearsquares[color][side] &
+ board->occupied) ||
+ board_squaresareattacked(board, castle_safesquares[color][side],
+ OTHERCOLOR(color))))
+ {
+ /* find where the king will end up */
+ destsquare = SQUARE(CASTLE_DEST_COL(side),
+ HOMEROW(color));
+ /* generate and add the move */
+ move = (square << MOV_INDEX_SRC) |
+ (destsquare << MOV_INDEX_DEST) |
+ (color << MOV_INDEX_COLOR) |
+ (0x1 << MOV_INDEX_CASTLE) |
+ (KING << MOV_INDEX_PIECE);
+ movelist_add(ml, board->attackedby, move);
+ }
+ }
+ }
+ /* now the special case is out of the way, the rest is simple. this
+ * could be a call to board_addmoves, but for move ordering purposes
+ * we do it separately. also, if we filter out suicide moves here,
+ * we avoid wasting time with applymove() in the searcher before
+ * seeing if the move is legal. */
+ /* inlined attacksfrom */
+ moves = kingattacks[square] & (~(board->piecesofcolor[color]));
+ /* here's the special part - we can't move the king anywhere where it
+ * will be in check - note, this still produces an illegal move if the
+ * king walks straight backward from a sliding piece, but we're only
+ * producing pseudo-legal moves, so this is merely an optimization.
+ * the movelist relies on not producing an obvious king-hang move. */
+ moves &= (~(board->attackedby[OTHERCOLOR(color)]));
+ /* the rest is the same as board_addmoves */
+ capts = moves & board->piecesofcolor[OTHERCOLOR(color)];
+ moves ^= capts;
+ /* that's a lie - the other special thing we do here is ordering so
+ * the king moves/capts are grouped with the pawn moves/capts */
+ while (capts)
+ {
+ /* find and clear a bit */
+ destsquare = BITSCAN(capts);
+ capts ^= BB_SQUARE(destsquare);
+ /* find what piece was captured */
+ captpiece = board_pieceatsquare(board, destsquare, NULL);
+ /* generate the move_t */
+ move = (square << MOV_INDEX_SRC) | /* from square */
+ (destsquare << MOV_INDEX_DEST) | /* to square */
+ (color << MOV_INDEX_COLOR) | /* color flag */
+ (0x1 << MOV_INDEX_CAPT) | /* capture flag */
+ (captpiece << MOV_INDEX_CAPTPC) | /* captured piece */
+ (KING << MOV_INDEX_PIECE); /* our piece */
+ /* and add it to the list */
+ movelist_add(ml, board->attackedby, move);
+ }
+ /* then process noncapture moves */
+ while (moves)
+ {
+ /* find and clear a bit */
+ destsquare = BITSCAN(moves);
+ moves ^= BB_SQUARE(destsquare);
+ /* generate the move_t */
+ move = (square << MOV_INDEX_SRC) | /* from square */
+ (destsquare << MOV_INDEX_DEST) | /* to square */
+ (color << MOV_INDEX_COLOR) | /* color flag */
+ (KING << MOV_INDEX_PIECE); /* our piece */
+ /* and add it to the list */
+ movelist_add(ml, board->attackedby, move);
+ }
+
+ return;
+}
+/* for non-special-case pieces: knight bishop rook queen. see above comment */
+static void board_addmoves(board_t *board, square_t square, piece_t piece, unsigned char color,
+ movelist_t *ml)
+{
+ bitboard_t moves, capts;
+ square_t destsquare;
+ piece_t captpiece;
+ move_t move;
+
+ /* find all destination squares -- all attacked squares, but can't
+ * capture our own pieces */
+ moves = board_attacksfrom(board, square, piece, color) & (~(board->piecesofcolor[color]));
+ /* separate captures from noncaptures */
+ capts = moves & board->piecesofcolor[OTHERCOLOR(color)];
+ moves ^= capts;
+ /* process captures first */
+ while (capts)
+ {
+ /* find and clear a bit */
+ destsquare = BITSCAN(capts);
+ capts ^= BB_SQUARE(destsquare);
+ /* find what piece was captured */
+ captpiece = board_pieceatsquare(board, destsquare, NULL);
+ /* generate the move_t */
+ move = (square << MOV_INDEX_SRC) | /* from square */
+ (destsquare << MOV_INDEX_DEST) | /* to square */
+ (color << MOV_INDEX_COLOR) | /* color flag */
+ (0x1 << MOV_INDEX_CAPT) | /* capture flag */
+ (captpiece << MOV_INDEX_CAPTPC) | /* captured piece */
+ (piece << MOV_INDEX_PIECE); /* our piece */
+ /* and add it to the list */
+ movelist_add(ml, board->attackedby, move);
+ }
+ /* then process noncapture moves */
+ while (moves)
+ {
+ /* find and clear a bit */
+ destsquare = BITSCAN(moves);
+ moves ^= BB_SQUARE(destsquare);
+ /* generate the move_t */
+ move = (square << MOV_INDEX_SRC) | /* from square */
+ (destsquare << MOV_INDEX_DEST) | /* to square */
+ (color << MOV_INDEX_COLOR) | /* color flag */
+ (piece << MOV_INDEX_PIECE); /* our piece */
+ /* and add it to the list */
+ movelist_add(ml, board->attackedby, move);
+ }
+ return;
+}
+
+/**
+ * The same as board_generatemoves, except we generate only captures. This is
+ * optimized to not even think about noncapture moves to be especially fast
+ * for quiescence searching.
+ */
+void board_generatecaptures(board_t *board, movelist_t *ml)
+{
+ bitboard_t position;
+ piece_t piece;
+ square_t square;
+ unsigned char color;
+
+ assert(board);
+
+ color = board->tomove;
+ movelist_init(ml);
+ /* same call as in addmoves... ep is always a capture */
+ if (board->ep)
+ {
+ //XXX: Take this out, as it won't help that much in quiescence? Depends on how fast it is
+ board_addmoves_ep(board, color, ml);
+ }
+ for (piece = 0; piece < 6; piece++)
+ {
+ position = board->pos[color][piece];
+ while (position)
+ {
+ /* find a piece */
+ square = BITSCAN(position);
+ /* clear the bit */
+ position ^= BB_SQUARE(square);
+ switch (piece)
+ {
+ case PAWN:
+ board_addcaptures_pawn(board, square, color, ml);
+ break;
+ case KING:
+ board_addcaptures_king(board, square, color, ml);
+ break;
+ default:
+ board_addcaptures(board, square, piece, color, ml);
+ }
+ }
+ }
+ return;
+}
+
+static void board_addcaptures_pawn(board_t *board, square_t square, unsigned char color, movelist_t *ml)
+{
+ bitboard_t moves;
+ square_t destsquare;
+ piece_t captpiece;
+ move_t move;
+ /* captures */
+ moves = pawnattacks[color][square] & /* inlined attacksfrom */
+ board->piecesofcolor[OTHERCOLOR(color)];
+ while (moves)
+ {
+ destsquare = BITSCAN(moves);
+ moves ^= BB_SQUARE(destsquare);
+ captpiece = board_pieceatsquare(board, destsquare, NULL);
+ move = (square << MOV_INDEX_SRC) |
+ (destsquare << MOV_INDEX_DEST) |
+ (color << MOV_INDEX_COLOR) |
+ (0x1 << MOV_INDEX_CAPT) |
+ (captpiece << MOV_INDEX_CAPTPC) |
+ (PAWN << MOV_INDEX_PIECE);
+ /* handle promotions */
+ if (ROW(destsquare) == HOMEROW(OTHERCOLOR(color)))
+ {
+ move |= (0x1 << MOV_INDEX_PROM);
+ movelist_add(ml, board->attackedby, (move | (BISHOP << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (ROOK << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (KNIGHT << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (QUEEN << MOV_INDEX_PROMPC)));
+ }
+ else /* normal capture */
+ {
+ movelist_add(ml, board->attackedby, move);
+ }
+ }
+ /* now we handle pushes only if it's a passed pawn */
+ if (board_pawnpassed(board, square, color))
+ {
+ moves = board_pawnpushesfrom(board, square, color);
+ /* and now we have the proper movemask generated */
+ while (moves)
+ {
+ destsquare = BITSCAN(moves);
+ moves ^= BB_SQUARE(destsquare);
+ move = (square << MOV_INDEX_SRC) |
+ (destsquare << MOV_INDEX_DEST) |
+ (color << MOV_INDEX_COLOR) |
+ (PAWN << MOV_INDEX_PIECE);
+ /* handle promotions */
+ if (ROW(destsquare) == HOMEROW(OTHERCOLOR(color)))
+ {
+ move |= (0x1 << MOV_INDEX_PROM);
+ movelist_add(ml, board->attackedby, (move | (BISHOP << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (ROOK << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (KNIGHT << MOV_INDEX_PROMPC)));
+ movelist_add(ml, board->attackedby, (move | (QUEEN << MOV_INDEX_PROMPC)));
+ }
+ else /* normal push */
+ {
+ movelist_add(ml, board->attackedby, move);
+ }
+ }
+ }
+ return;
+}
+
+static void board_addcaptures_king(board_t *board, square_t square, unsigned char color, movelist_t *ml)
+{
+ move_t move;
+ square_t destsquare;
+ bitboard_t moves, capts;
+ piece_t captpiece;
+
+ /* No dealing with castling! :D this is the same as addcaptures() but
+ * again we do the special thing */
+ /* inlined attacksfrom */
+ moves = kingattacks[square] & (~(board->piecesofcolor[color]));
+ moves &= (~(board->attackedby[OTHERCOLOR(color)]));
+ capts = moves & board->piecesofcolor[OTHERCOLOR(color)];
+ moves ^= capts;
+ /* like in regular movegen, captures by king go at the beginning */
+ while (capts)
+ {
+ /* find and clear a bit */
+ destsquare = BITSCAN(capts);
+ capts ^= BB_SQUARE(destsquare);
+ /* find what piece was captured */
+ captpiece = board_pieceatsquare(board, destsquare, NULL);
+ /* generate the move_t */
+ move = (square << MOV_INDEX_SRC) | /* from square */
+ (destsquare << MOV_INDEX_DEST) | /* to square */
+ (color << MOV_INDEX_COLOR) | /* color flag */
+ (0x1 << MOV_INDEX_CAPT) | /* capture flag */
+ (captpiece << MOV_INDEX_CAPTPC) | /* captured piece */
+ (KING << MOV_INDEX_PIECE); /* our piece */
+ /* and add it to the list */
+ movelist_add(ml, board->attackedby, move);
+ }
+ return;
+}
+
+static void board_addcaptures(board_t *board, square_t square, piece_t piece, unsigned char color, movelist_t *ml)
+{
+ bitboard_t moves, capts;
+ square_t destsquare;
+ piece_t captpiece;
+ move_t move;
+
+ /* find all destination squares -- all attacked squares, but can't
+ * capture our own pieces */
+ moves = board_attacksfrom(board, square, piece, color) &
+ (~(board->piecesofcolor[color]));
+ /* separate captures from noncaptures */
+ capts = moves & board->piecesofcolor[OTHERCOLOR(color)];
+ moves ^= capts;
+ /* process captures first */
+ while (capts)
+ {
+ /* find and clear a bit */
+ destsquare = BITSCAN(capts);
+ capts ^= BB_SQUARE(destsquare);
+ /* find what piece was captured */
+ captpiece = board_pieceatsquare(board, destsquare, NULL);
+ /* generate the move_t */
+ move = (square << MOV_INDEX_SRC) | /* from square */
+ (destsquare << MOV_INDEX_DEST) | /* to square */
+ (color << MOV_INDEX_COLOR) | /* color flag */
+ (0x1 << MOV_INDEX_CAPT) | /* capture flag */
+ (captpiece << MOV_INDEX_CAPTPC) | /* captured piece */
+ (piece << MOV_INDEX_PIECE); /* our piece */
+ /* and add it to the list */
+ movelist_add(ml, board->attackedby, move);
+ }
+ return;
+}
+
+
+/***********************
+ * Changing board state
+ ***********************/
+
+/**
+ * Given a move, which MUST be properly formatted AND legal (only use moves
+ * returned by board_generatemoves() or move_islegal() here), applies the move
+ * to change the board position. Updates the zobrist hash, undo stacks,
+ * everything.
+ */
+void board_applymove(board_t *board, move_t move)
+{
+ square_t rooksrc, rookdest; /* how the rook moves in castling */
+ square_t epcapture; /* where a pawn will disappear from */
+ int i;
+
+ /* save history. */
+ history_t *h = &board->history[board->moves];
+ affirm(board->moves < HISTORY_STACK_SIZE);
+ h->hash = board->hash;
+ h->attackedby[WHITE] = board->attackedby[WHITE];
+ h->attackedby[BLACK] = board->attackedby[BLACK];
+ h->castle[WHITE][QUEENSIDE] = board->castle[WHITE][QUEENSIDE];
+ h->castle[WHITE][KINGSIDE] = board->castle[WHITE][KINGSIDE];
+ h->castle[BLACK][QUEENSIDE] = board->castle[BLACK][QUEENSIDE];
+ h->castle[BLACK][KINGSIDE] = board->castle[BLACK][KINGSIDE];
+ h->ep = board->ep;
+ h->halfmoves = board->halfmoves;
+ h->reps = board->reps;
+ h->move = move;
+
+ /* cleanly handle null-move */
+ if (move == 0)
+ {
+ /* clear ep square */
+ board->hash ^= zobrist_ep[board->ep];
+ board->ep = 0;
+ board->hash ^= zobrist_ep[board->ep];
+ /* update the move clock */
+ board->halfmoves++;
+ board->moves++;
+ /* null move is illegal, so it can't cause a threefold draw */
+ board->reps = 0;
+ /* switch who has the move */
+ board->tomove = OTHERCOLOR(board->tomove);
+ board->hash ^= zobrist_tomove;
+ return;
+ }
+
+ assert(MOV_PIECE(move) >= 0 && MOV_PIECE(move) < 6);
+
+ /* Take care of captures - we need to remove the captured piece. */
+ if (MOV_CAPT(move))
+ {
+ /* special case - en passant - square behind the dest square */
+ if (MOV_EP(move))
+ {
+ assert(ROW(MOV_SRC(move)) == 4 - board->tomove);
+ /* find where the pawn disappears from */
+ epcapture = (board->tomove == WHITE) ?
+ (MOV_DEST(move) - 8) :
+ (MOV_DEST(move) + 8);
+ /* kill the pawn */
+ board_togglepiece(board, epcapture,
+ OTHERCOLOR(board->tomove), PAWN);
+ /* change the material count */
+ board->material[OTHERCOLOR(board->tomove)] -=
+ eval_piecevalue[PAWN];
+ }
+ /* standard capture - square is the dest square */
+ else
+ {
+ board_togglepiece(board, MOV_DEST(move),
+ OTHERCOLOR(board->tomove),
+ MOV_CAPTPC(move));
+ /* If the captured piece is a rook on its home square,
+ * and the player was still able to castle that side,
+ * we need to clear the castle privileges there */
+ if (MOV_CAPTPC(move) == ROOK &&
+ ROW(MOV_DEST(move)) == HOMEROW(OTHERCOLOR(board->tomove)) &&
+ (COL(MOV_DEST(move)) == COL_H ||
+ COL(MOV_DEST(move)) == COL_A))
+ {
+ /* (COLUMN == COL_H) will evaluate to 1 if on
+ * KINGSIDE (this depends on KINGSIDE == 1) */
+ unsigned char side = (COL(MOV_DEST(move)) == COL_H);
+ /* if castle rights is already gone there, we
+ * don't do anything. this is important when
+ * toggling the zobrist */
+ if (board->castle[OTHERCOLOR(board->tomove)][side])
+ {
+ board->castle[OTHERCOLOR(board->tomove)][side] = 0;
+ board->hash ^= zobrist_castle[OTHERCOLOR(board->tomove)]
+ [side];
+ }
+
+ }
+ /* change the material count */
+ board->material[OTHERCOLOR(board->tomove)] -=
+ eval_piecevalue[MOV_CAPTPC(move)];
+ }
+ board->halfmoves = 0;
+ }
+ /* here we detect irreversible moves for the halfmove clock */
+ else
+ {
+ if (MOV_PIECE(move) == PAWN)
+ {
+ board->halfmoves = 0;
+ }
+ else
+ {
+ board->halfmoves++;
+ }
+ }
+ /* the game clock as well */
+ board->moves++;
+
+ /* castling, need to move the rook. castle privileges handled below */
+ if (MOV_CASTLE(move))
+ {
+ /* detect kingside vs queenside */
+ if (COL(MOV_DEST(move)) == COL_G)
+ {
+ rooksrc = SQUARE(COL_H,HOMEROW(board->tomove));
+ rookdest = SQUARE(COL_F,HOMEROW(board->tomove));
+ }
+ else
+ {
+ rooksrc = SQUARE(COL_A,HOMEROW(board->tomove));
+ rookdest = SQUARE(COL_D,HOMEROW(board->tomove));
+ }
+ /* and move the rook */
+ board_togglepiece(board, rooksrc, board->tomove, ROOK);
+ board_togglepiece(board, rookdest, board->tomove, ROOK);
+ /* set the flag */
+ board->hascastled[board->tomove] = 1;
+ }
+
+ /* here we move the moving piece itself; in the former case it turns
+ * into a different type of piece */
+ board_togglepiece(board, MOV_SRC(move), board->tomove,
+ MOV_PIECE(move));
+ if (MOV_PROM(move))
+ {
+ assert(ROW(MOV_DEST(move)) ==
+ HOMEROW(OTHERCOLOR(board->tomove)));
+ board_togglepiece(board, MOV_DEST(move), board->tomove,
+ MOV_PROMPC(move));
+ /* and of course account for this in the material count */
+ board->material[board->tomove] +=
+ (eval_piecevalue[MOV_PROMPC(move)] -
+ eval_piecevalue[PAWN]);
+ }
+ else
+ {
+ board_togglepiece(board, MOV_DEST(move), board->tomove,
+ MOV_PIECE(move));
+ }
+
+ /* detect an enpassantable move */
+ if (MOV_PIECE(move) == PAWN)
+ {
+ /* if the difference between the square values is 16 not 8
+ * then it was a double push */
+ if ((board->tomove == WHITE) &&
+ ((MOV_DEST(move) - MOV_SRC(move)) == 16))
+ {
+ /* clear the old ep status in the hash */
+ board->hash ^= zobrist_ep[board->ep];
+ /* set the new value */
+ board->ep = MOV_SRC(move) + 8;
+ /* throw in the new key */
+ board->hash ^= zobrist_ep[board->ep];
+ }
+ else if ((board->tomove == BLACK) &&
+ ((MOV_SRC(move) - MOV_DEST(move)) == 16))
+ {
+ board->hash ^= zobrist_ep[board->ep];
+ board->ep = MOV_DEST(move) + 8;
+ board->hash ^= zobrist_ep[board->ep];
+ }
+ else
+ {
+ board->hash ^= zobrist_ep[board->ep];
+ board->ep = 0;
+ board->hash ^= zobrist_ep[board->ep];
+ }
+ }
+ /* not a pawn move. ep square goes away. */
+ else
+ {
+ board->hash ^= zobrist_ep[board->ep];
+ board->ep = 0;
+ board->hash ^= zobrist_ep[board->ep];
+ /* handle castling rights */
+ if (MOV_PIECE(move) == KING)
+ {
+ if (board->castle[board->tomove][KINGSIDE])
+ {
+ board->castle[board->tomove][KINGSIDE] = 0;
+ board->hash ^= zobrist_castle[board->tomove][KINGSIDE];
+ }
+ if (board->castle[board->tomove][QUEENSIDE])
+ {
+ board->castle[board->tomove][QUEENSIDE] = 0;
+ board->hash ^= zobrist_castle[board->tomove][QUEENSIDE];
+ }
+ }
+ else if (MOV_PIECE(move) == ROOK)
+ {
+ if ((board->castle[board->tomove][KINGSIDE]) &&
+ (COL(MOV_SRC(move)) == COL_H))
+ {
+ board->castle[board->tomove][KINGSIDE] = 0;
+ board->hash ^= zobrist_castle[board->tomove][KINGSIDE];
+ }
+ else if ((board->castle[board->tomove][QUEENSIDE]) &&
+ (COL(MOV_SRC(move)) == COL_A))
+ {
+ board->castle[board->tomove][QUEENSIDE] = 0;
+ board->hash ^= zobrist_castle[board->tomove][QUEENSIDE];
+ }
+ }
+ }
+
+ /* switch who has the move */
+ board->tomove = OTHERCOLOR(board->tomove);
+ board->hash ^= zobrist_tomove;
+
+ /* calculate repetition count */
+ board->reps = 0;
+ for (i = 1; i <= board->halfmoves; i++)
+ {
+ if (board->history[board->moves - i].hash == board->hash)
+ {
+ board->reps = board->history[board->moves - i].reps+1;
+ break;
+ }
+ }
+
+ /* and finally */
+ board_regeneratethreatened(board);
+ return;
+}
+
+/**
+ * Go back one move. The cleaner implementation is to keep a stack of the
+ * moves, but it's faster to have the searcher/legalitychecker just pass in
+ * the move again rather than mucking about with data structures.
+ * Note if you pass in a move different from the one that was most recently
+ * made, the board state will choke and die horribly.
+ */
+void board_undomove(board_t *board, move_t move)
+{
+ square_t rooksrc, rookdest, epcapture;
+
+ /* switch who has the move */
+ board->tomove = OTHERCOLOR(board->tomove);
+ board->hash ^= zobrist_tomove;
+
+ /* cleanly handle null-move */
+ if (move == 0)
+ {
+ board->moves--;
+ board->halfmoves--;
+ board->hash ^= zobrist_ep[board->ep];
+ board->ep = board->history[board->moves].ep;
+ board->hash ^= zobrist_ep[board->ep];
+ board->reps = board->history[board->moves].reps;
+ return;
+ }
+
+ /* The non-special things (see bottom of function for special things)
+ * are basically applymove in reverse. First move the piece back. */
+ board_togglepiece(board, MOV_SRC(move), board->tomove, MOV_PIECE(move));
+ if (MOV_PROM(move))
+ {
+ board_togglepiece(board, MOV_DEST(move), board->tomove,
+ MOV_PROMPC(move));
+ /* material count */
+ board->material[board->tomove] -=
+ (eval_piecevalue[MOV_PROMPC(move)] -
+ eval_piecevalue[PAWN]);
+ }
+ else
+ {
+ board_togglepiece(board, MOV_DEST(move), board->tomove,
+ MOV_PIECE(move));
+ }
+ /* castling, need to move the rook back. */
+ if (MOV_CASTLE(move))
+ {
+ /* detect kingside vs queenside */
+ if (COL(MOV_DEST(move)) == COL_G)
+ {
+ /* note src is where it needs to end up because we're
+ * moving backwards not forwards */
+ rooksrc = SQUARE(COL_H,HOMEROW(board->tomove));
+ rookdest = SQUARE(COL_F,HOMEROW(board->tomove));
+ }
+ else
+ {
+ rooksrc = SQUARE(COL_A,HOMEROW(board->tomove));
+ rookdest = SQUARE(COL_D,HOMEROW(board->tomove));
+ }
+ /* and move the rook */
+ board_togglepiece(board, rooksrc, board->tomove, ROOK);
+ board_togglepiece(board, rookdest, board->tomove, ROOK);
+ /* flag */
+ board->hascastled[board->tomove] = 0;
+ }
+ /* for captures, put the captured piece back */
+ if (MOV_CAPT(move))
+ {
+ /* special case - en passant - square behind the dest square */
+ if (MOV_EP(move))
+ {
+ epcapture = (board->tomove == WHITE) ?
+ (MOV_DEST(move) - 8) :
+ (MOV_DEST(move) + 8);
+ board_togglepiece(board, epcapture,
+ OTHERCOLOR(board->tomove), PAWN);
+ board->material[OTHERCOLOR(board->tomove)] +=
+ eval_piecevalue[PAWN];
+ }
+ /* standard capture - square is the dest square */
+ else
+ {
+ board_togglepiece(board, MOV_DEST(move),
+ OTHERCOLOR(board->tomove),
+ MOV_CAPTPC(move));
+ board->material[OTHERCOLOR(board->tomove)] +=
+ eval_piecevalue[MOV_CAPTPC(move)];
+ }
+ }
+
+ /* decrement the game clock */
+ board->moves--;
+
+ /* Get the previous special board state information from the stacks */
+ board->attackedby[WHITE] = board->history[board->moves].attackedby[WHITE];
+ board->attackedby[BLACK] = board->history[board->moves].attackedby[BLACK];
+
+ /* clear the old castle keys */
+ if (board->castle[WHITE][QUEENSIDE]) { board->hash ^= zobrist_castle[WHITE][QUEENSIDE]; }
+ if (board->castle[WHITE][KINGSIDE]) { board->hash ^= zobrist_castle[WHITE][KINGSIDE]; }
+ if (board->castle[BLACK][QUEENSIDE]) { board->hash ^= zobrist_castle[BLACK][QUEENSIDE]; }
+ if (board->castle[BLACK][KINGSIDE]) { board->hash ^= zobrist_castle[BLACK][KINGSIDE]; }
+ /* set the new castle rights */
+ board->castle[WHITE][QUEENSIDE] = board->history[board->moves].castle[WHITE][QUEENSIDE];
+ board->castle[WHITE][KINGSIDE] = board->history[board->moves].castle[WHITE][KINGSIDE];
+ board->castle[BLACK][QUEENSIDE] = board->history[board->moves].castle[BLACK][QUEENSIDE];
+ board->castle[BLACK][KINGSIDE] = board->history[board->moves].castle[BLACK][KINGSIDE];
+ /* set the new castle keys */
+ if (board->castle[WHITE][QUEENSIDE]) { board->hash ^= zobrist_castle[WHITE][QUEENSIDE]; }
+ if (board->castle[WHITE][KINGSIDE]) { board->hash ^= zobrist_castle[WHITE][KINGSIDE]; }
+ if (board->castle[BLACK][QUEENSIDE]) { board->hash ^= zobrist_castle[BLACK][QUEENSIDE]; }
+ if (board->castle[BLACK][KINGSIDE]) { board->hash ^= zobrist_castle[BLACK][KINGSIDE]; }
+
+ /* restore ep information */
+ board->hash ^= zobrist_ep[board->ep];
+ board->ep = board->history[board->moves].ep;
+ board->hash ^= zobrist_ep[board->ep];
+
+ /* set the halfmove clock */
+ board->halfmoves = board->history[board->moves].halfmoves;
+
+ /* and repetitions */
+ board->reps = board->history[board->moves].reps;
+
+ /* consistency check */
+ assert(board->hash == board->history[board->moves].hash);
+ assert(move == board->history[board->moves].move);
+ return;
+}
+
+/**
+ * The togglepiece function is a wrapper to simplify moving pieces around on
+ * the board. They modify the bits in the piece-specific position masks, the
+ * all-pieces-of-one-color mask, and in the four occupied boards, and adjust
+ * the zobrist hash.
+ */
+static void board_togglepiece(board_t *board, square_t square,
+ unsigned char color, piece_t piece)
+{
+ /* no other piece ought be on this square */
+ assert(!(board->occupied & BB_SQUARE(square) &
+ ~board->pos[color][piece]));
+ /* piece-specific position mask */
+ board->pos[color][piece] ^= BB_SQUARE(square);
+
+ /* all the color's pieces */
+ board->piecesofcolor[color] ^= BB_SQUARE(square);
+
+ /* general occupied masks */
+ board->occupied ^= BB_SQUARE(square);
+ board->occupied90 ^= BB_SQUARE(ROT90SQUAREINDEX(square));
+ board->occupied45 ^= BB_SQUARE(ROT45SQUAREINDEX(square));
+ board->occupied315 ^= BB_SQUARE(ROT315SQUAREINDEX(square));
+
+ /* adjust the zobrist */
+ board->hash ^= zobrist_piece[color][piece][square];
+}
+
+/**
+ * This hashtable stores threatened square masks so we don't have to always
+ * regenerate them.
+ */
+typedef struct {
+ bitboard_t key;
+ bitboard_t white;
+ bitboard_t black;
+} regen_entry_t;
+
+#ifndef REGEN_NUM_BUCKETS
+#define REGEN_NUM_BUCKETS (32 * 1024 * 1024 / sizeof(regen_entry_t)) // 32 MB
+#endif
+static regen_entry_t regen_array[REGEN_NUM_BUCKETS];
+
+static void regen_add(bitboard_t key, bitboard_t white, bitboard_t black)
+{
+ unsigned long bucket = key % REGEN_NUM_BUCKETS;
+ regen_array[bucket].key = key;
+ regen_array[bucket].white = white;
+ regen_array[bucket].black = black;
+}
+
+static int regen_get(bitboard_t key, bitboard_t *white, bitboard_t *black)
+{
+ unsigned long bucket = key % REGEN_NUM_BUCKETS;
+ if (regen_array[bucket].key == key)
+ {
+ *white = regen_array[bucket].white;
+ *black = regen_array[bucket].black;
+ return 1;
+ }
+ return 0;
+}
+
+int regen_hits = 0;
+int regen_misses = 0;
+
+/**
+ * Regenerate the threatened squares masks for both sides. Should be used when
+ * a move is made. Don't use in undomove, use the special stacks instead
+ */
+static void board_regeneratethreatened(board_t *board)
+{
+ bitboard_t mask;
+ bitboard_t position;
+ piece_t piece;
+ square_t square;
+
+ /* check hashtable */
+ if (regen_get(board->hash,
+ &board->attackedby[WHITE], &board->attackedby[BLACK]))
+ {
+ regen_hits++;
+ return;
+ }
+
+ /********
+ * White
+ ********/
+ mask = BB(0x0);
+ /* pawn threatened can be done for all pawns at once */
+ mask |= board_pawnattacks(board->pos[WHITE][PAWN], WHITE);
+ /* Knights and kings manually inlined */
+ position = board->pos[WHITE][KNIGHT];
+ while (position)
+ {
+ square = BITSCAN(position);
+ position ^= BB_SQUARE(square);
+ mask |= knightattacks[square];
+ }
+ position = board->pos[WHITE][KING];
+ while(position)
+ {
+ square = BITSCAN(position);
+ position ^= BB_SQUARE(square);
+ mask |= kingattacks[square];
+ }
+ /* other piece threatened */
+ for (piece = 2; piece < 5; piece++)
+ {
+ position = board->pos[WHITE][piece];
+ /* keep going until we've found all the pieces */
+ while (position)
+ {
+ /* Find one of the pieces, clear its bit */
+ square = BITSCAN(position);
+ position ^= BB_SQUARE(square);
+ /* Put the attacks from this square in the mask */
+ mask |= board_attacksfrom(board, square, piece, WHITE);
+ }
+ }
+ board->attackedby[WHITE] = mask;
+ /********
+ * Black
+ ********/
+ mask = BB(0x0);
+ /* pawn threatened can be done for all pawns at once */
+ mask |= board_pawnattacks(board->pos[BLACK][PAWN], BLACK);
+ /* Knights and kings manually inlined */
+ position = board->pos[BLACK][KNIGHT];
+ while (position)
+ {
+ square = BITSCAN(position);
+ position ^= BB_SQUARE(square);
+ mask |= knightattacks[square];
+ }
+ position = board->pos[BLACK][KING];
+ while(position)
+ {
+ square = BITSCAN(position);
+ position ^= BB_SQUARE(square);
+ mask |= kingattacks[square];
+ }
+ /* other piece threatened */
+ for (piece = 2; piece < 5; piece++)
+ {
+ position = board->pos[BLACK][piece];
+ /* keep going until we've found all the pieces */
+ while (position)
+ {
+ /* Find one of the pieces, clear its bit */
+ square = BITSCAN(position);
+ position ^= BB_SQUARE(square);
+ /* Put the attacks from this square in the mask */
+ mask |= board_attacksfrom(board, square, piece, BLACK);
+ }
+ }
+ board->attackedby[BLACK] = mask;
+
+ /* save to hashtable */
+ regen_add(board->hash, board->attackedby[WHITE], board->attackedby[BLACK]);
+ regen_misses++;
+
+ return;
+}
+
+/**
+ * Get a bitmap of all squares attacked by the pawns in the given position of
+ * the given color. Used by regenthreatened, and also in pawnstructure eval
+ */
+bitboard_t board_pawnattacks(bitboard_t pawns, unsigned char color)
+{
+ /* a-pawns don't attack left; h-pawns don't attack right */
+ if (color == WHITE)
+ {
+ return ((pawns & ~BB_FILEA) << 7) | ((pawns & ~BB_FILEH) << 9);
+ }
+ else
+ {
+ return ((pawns & ~BB_FILEA) >> 9) | ((pawns & ~BB_FILEH) >> 7);
+ }
+}
+
+/**
+ * Is the current position a threefold draw?
+ */
+int board_threefold_draw(board_t *board)
+{
+ return board->reps >= 2;
+}
+
+/****************************************************************************
+ * END: BITBOARD FUNCTIONS
+ * BEGIN: MOVE FUNCTIONS
+ ****************************************************************************/
+
+static move_t move_checksuicide(board_t *, move_t, char **);
+
+/**
+ * Parses computer friendly ("d7c8N" or "e1g1") notation to generate a simple
+ * move_t template. Will return 0 on a malformatted move (note 0 is never a
+ * valid move_t). This will only set the prom flag, not castle/ep/capt. As a
+ * result, the resultant move is not suitable for throwing directly into
+ * applyMove.
+ */
+move_t move_fromstring(char *str)
+{
+ size_t length = strlen(str);
+ move_t move = 0;
+
+ /* check for malformatted move string */
+ if (length < 4 || length > 5 || /* too short/long */
+ !(str[0] >= 'a' && str[0] <= 'h') || /* bad src/dest squares */
+ !(str[1] >= '1' && str[1] <= '8') ||
+ !(str[2] >= 'a' && str[2] <= 'h') ||
+ !(str[3] >= '1' && str[3] <= '8') ||
+ (length == 5 && /* bad promotion piece */
+ !(str[4] == 'N' || str[4] == 'B' ||
+ str[4] == 'R' || str[4] == 'Q' ||
+ str[4] == 'n' || str[4] == 'b' ||
+ str[4] == 'r' || str[4] == 'q')))
+ {
+ return (move_t)0;
+ }
+
+ /* set the src and dest */
+ move |= SQUARE((str[0] - 'a'), (str[1] - '1')) << MOV_INDEX_SRC;
+ move |= SQUARE((str[2] - 'a'), (str[3] - '1')) << MOV_INDEX_DEST;
+
+ /* promotion */
+ if (length == 5)
+ {
+ move |= 1 << MOV_INDEX_PROM; /* set the flag */
+ switch(str[4])
+ {
+ case 'N':
+ case 'n':
+ move |= KNIGHT << MOV_INDEX_PROMPC;
+ break;
+ case 'B':
+ case 'b':
+ move |= BISHOP << MOV_INDEX_PROMPC;
+ break;
+ case 'R':
+ case 'r':
+ move |= ROOK << MOV_INDEX_PROMPC;
+ break;
+ default:
+ move |= QUEEN << MOV_INDEX_PROMPC;
+ }
+ }
+
+ return move;
+}
+
+/**
+ * A more advanced form of move_fromstring. Given also a board_t, will return
+ * a move_t for the move represented by str if it is 1) properly formatted,
+ * 2) valid, 3) legal. Otherwise returns 0. All appropriate flags will be set,
+ * so this is suitable for applymove.
+ * This code is not fast, as it will apply/undo the move from the board. Use
+ * it for checking the opponent's move, not the engine's move.
+ */
+move_t move_islegal(board_t *board, char *str, char **errmsg)
+{
+ move_t move;
+ square_t src, dest;
+ piece_t piece;
+ bitboard_t moves, clearsquares;
+
+ /* Parse the string */
+ move = move_fromstring(str);
+ src = MOV_SRC(move);
+ dest = MOV_DEST(move);
+
+ /* First check: sanity; this also handles if move_fromstring failed */
+ if (src == dest)
+ {
+ *errmsg = "!!! Motion is required for a move.";
+ return 0;
+ }
+ /* Does this piece belong to us */
+ if (!(BB_SQUARE(src) & board->piecesofcolor[board->tomove]))
+ {
+ *errmsg = "!!! You don't have a piece there.";
+ return 0;
+ }
+
+ /* Find our piece and where it can go */
+ piece = board_pieceatsquare(board, src, NULL);
+ moves = board_attacksfrom(board, src, piece, board->tomove) &
+ (~(board->piecesofcolor[board->tomove])); /* can't capture own piece */
+ move |= piece << MOV_INDEX_PIECE; /* set the piece-type flag */
+
+ /* of course, pawns and kings are special... */
+ if (piece == PAWN) /* pushes and enpassants */
+ {
+ /* can't make an attacking move unless it's a capture */
+ moves &= board->piecesofcolor[OTHERCOLOR(board->tomove)];
+ /* Trying to make an illegal promotion, or not promoting on an
+ * advance to the promotion rank */
+ if ((!!(MOV_PROM(move))) ^
+ (!!(ROW(dest) == HOMEROW(OTHERCOLOR(board->tomove)))))
+ {
+ if (!!(MOV_PROM(move))) {
+ *errmsg = "!!! Pawns don't promote like that.";
+ } else {
+ *errmsg = "!!! Promote into what? (N/B/R/Q)";
+ }
+ return 0;
+ }
+ /* move is a regular capture */
+ if (BB_SQUARE(dest) & moves)
+ {
+ move |= 1 << MOV_INDEX_CAPT;
+ move |= board_pieceatsquare(board, dest, NULL) << MOV_INDEX_CAPTPC;
+ return move_checksuicide(board, move, errmsg);
+ }
+ /* enpassant */
+ if (board->ep && dest == board->ep)
+ {
+ move |= (0x1 << MOV_INDEX_EP) |
+ (0x1 << MOV_INDEX_CAPT) |
+ (PAWN << MOV_INDEX_CAPTPC);
+ return move_checksuicide(board, move, errmsg);
+ }
+ /* check for push */
+ clearsquares = ~board->occupied;
+ /* is pawn free to move one square ahead? we don't need to set
+ * any special additional flags here */
+ if (pawnmoves[board->tomove][src] & clearsquares)
+ {
+ /* Are we trying to move 1 square ahead? Note: relies
+ * on the fact that pawnmoves[][] has one bit set. */
+ if (BB_SQUARE(dest) == pawnmoves[board->tomove][src])
+ {
+ return move_checksuicide(board, move, errmsg);
+ }
+ /* 2-square push from 2nd rank */
+ if (((board->tomove == WHITE) &&
+ (pawnmoves[board->tomove][src+8] & clearsquares) &&
+ (BB_SQUARE(dest) == pawnmoves[board->tomove][src+8])) ||
+ ((board->tomove == BLACK) &&
+ (pawnmoves[board->tomove][src-8] & clearsquares) &&
+ (BB_SQUARE(dest) == pawnmoves[board->tomove][src-8])))
+ {
+ return move_checksuicide(board, move, errmsg);
+ }
+ }
+ *errmsg = "!!! Pawns can't move like that.";
+ return 0;
+ }
+ /* not a pawn, trying to promote a different piece */
+ else if (MOV_PROM(move))
+ {
+ *errmsg = "!!! You can't promote non-pawns!";
+ return 0;
+ }
+ /* note - for king moves, we don't need to apply the move to check if
+ * it puts the player in check; we use squareisattacked() directly */
+ else if (piece == KING)
+ {
+ /* handle castling - queenside */
+ if (board->castle[board->tomove][QUEENSIDE] &&
+ (src == SQUARE(COL_E,HOMEROW(board->tomove))) &&
+ (dest == SQUARE(COL_C,HOMEROW(board->tomove)))) /* "e1c1" or "e8c8" */
+ {
+ /* check if special squares are blocked or attacked */
+ if (castle_clearsquares[board->tomove][QUEENSIDE] & board->occupied) {
+ *errmsg = "!!! Castling squares are blocked.";
+ return 0;
+ } else if (board_squaresareattacked(board, castle_safesquares[board->tomove][QUEENSIDE], OTHERCOLOR(board->tomove))) {
+ *errmsg = "!!! Can't castle through check.";
+ return 0;
+ }
+ /* here, the castle is legal */
+ move |= 0x1 << MOV_INDEX_CASTLE;
+ return move;
+ }
+ /* kingside */
+ if (board->castle[board->tomove][KINGSIDE] &&
+ (src == SQUARE(COL_E,HOMEROW(board->tomove))) &&
+ (dest == SQUARE(COL_G,HOMEROW(board->tomove)))) /* "e1g1" or "e8g8" */
+ {
+ /* check if special squares are blocked or attacked */
+ if (castle_clearsquares[board->tomove][KINGSIDE] & board->occupied) {
+ *errmsg = "!!! Castling squares are blocked.";
+ return 0;
+ } else if (board_squaresareattacked(board, castle_safesquares[board->tomove][KINGSIDE], OTHERCOLOR(board->tomove))) {
+ *errmsg = "!!! Can't castle through check.";
+ return 0;
+ }
+ /* here, the castle is legal */
+ move |= 0x1 << MOV_INDEX_CASTLE;
+ return move;
+ }
+ /* otherwise it must be a normal king move to be legal */
+ /* we can make this move */
+ if (BB_SQUARE(dest) & moves)
+ {
+ /* making a capture */
+ if (BB_SQUARE(dest) & board->piecesofcolor[OTHERCOLOR(board->tomove)])
+ {
+ move |= 1 << MOV_INDEX_CAPT;
+ move |= board_pieceatsquare(board, dest, NULL) << MOV_INDEX_CAPTPC;
+ }
+ if (board_squareisattacked(board, dest, OTHERCOLOR(board->tomove)))
+ {
+ *errmsg = "!!! Can't move king into check.";
+ return 0;
+ }
+ return move;
+ }
+ *errmsg = "!!! Kings can't move like that.";
+ return 0;
+ }
+ /* typical case piece - N B R Q */
+ else
+ {
+ /* is this one of our legal moves? */
+ if (BB_SQUARE(dest) & moves)
+ {
+ /* making a capture? */
+ if (BB_SQUARE(dest) & board->piecesofcolor[OTHERCOLOR(board->tomove)])
+ {
+ move |= 1 << MOV_INDEX_CAPT;
+ move |= board_pieceatsquare(board, dest, NULL) << MOV_INDEX_CAPTPC;
+ }
+ return move_checksuicide(board, move, errmsg);
+ }
+ *errmsg =
+ piece == QUEEN ? "!!! Queens can't move like that." :
+ piece == ROOK ? "!!! Rooks can't move like that." :
+ piece == BISHOP ? "!!! Bishops can't move like that." :
+ "!!! Knights can't move like that.";
+ return 0;
+ }
+}
+
+/**
+ * Given a move on a given position (must be legal and suitably formatted for
+ * applymove), check if making this move would leave the player in check.
+ * Returns the move if it's good, 0 if not.
+ */
+static move_t move_checksuicide(board_t *board, move_t move, char **errmsg)
+{
+ board_applymove(board, move);
+ if (board_colorincheck(board, OTHERCOLOR(board->tomove)))
+ {
+ board_undomove(board, move);
+ *errmsg = "!!! That would put you in check.";
+ return 0;
+ }
+ board_undomove(board, move);
+ return move;
+}
+
+/**
+ * Returns the string representation of a move in computer-friendly format
+ * (that is, "squarename[src]squarename[dest]promotionpiece"). Free the string
+ * when you're done with it.
+ */
+char *move_tostring(move_t m)
+{
+ char *string;
+ /* longest move in this format is a promotion, "a7a8Q" */
+ string = malloc(6);
+ affirm_msg(string, "Couldn't allocate move string");
+ string[0] = 0;
+ strcat(string, squarename[MOV_SRC(m)]);
+ strcat(string, squarename[MOV_DEST(m)]);
+ if (MOV_PROM(m))
+ {
+ /* use WHITE as an index to get the uppercase */
+ strcat(string, piecename[WHITE][MOV_PROMPC(m)]);
+ }
+ return string;
+}
+/****************************************************************************
+ * book.c - simple interface for retrieving moves from a plaintext book
+ * copyright (C) 2008 Ben Blum
+ * ****************************************************************************/
+
+#define BOOK_MOVE_LENGTH 4
+
+// Must be sorted.
+const char *book[] = {
+ "c2c4 c7c5 g1f3 b8c6",
+ "c2c4 c7c5 g1f3 g8f6 b1c3 b8c6",
+ "c2c4 c7c5 g1f3 g8f6 b1c3 e7e6 g2g3 b7b6 f1g2 c8b7 e1g1 f8e7",
+ "c2c4 c7c5 g1f3 g8f6 g2g3",
+ "c2c4 c7c6",
+ "c2c4 e7e5 b1c3 b8c6",
+ "c2c4 e7e5 b1c3 g8f6 g1f3 b8c6 g2g3",
+ "c2c4 e7e5 g2g3",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 c7c6",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 f8e7 g1f3 g8f6 c1f4 e8g8 e2e3",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 f8e7 g1f3 g8f6 c1g5 e8g8 e2e3 h7h6",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 f8e7 g1f3 g8f6 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 c1g5 f8e7 e2e3",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 c4d5 e6d5 c1g5",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 b8d7",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 c7c5",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 c7c6 c1g5",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 f8b4",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 f8e7 c1f4 e8g8 e2e3",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "c2c4 e7e6 b1c3 d7d5 d2d4 g8f6 g1f3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "c2c4 e7e6 g1f3",
+ "c2c4 g8f6 b1c3 c7c5",
+ "c2c4 g8f6 b1c3 e7e5 g1f3 b8c6 g2g3",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 b8d7",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 c7c5",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 c7c6 c1g5",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 f8b4",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 f8e7 c1f4 e8g8 e2e3",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "c2c4 g8f6 b1c3 e7e6 g1f3 d7d5 d2d4 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "c2c4 g8f6 b1c3 g7g6",
+ "c2c4 g8f6 g1f3 b7b6 g2g3",
+ "c2c4 g8f6 g1f3 c7c5 b1c3 b8c6",
+ "c2c4 g8f6 g1f3 c7c5 b1c3 e7e6 g2g3 b7b6 f1g2 c8b7 e1g1 f8e7",
+ "c2c4 g8f6 g1f3 c7c5 g2g3",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 b8d7",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 c7c5",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 c7c6 c1g5",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 f8b4",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 f8e7 c1f4 e8g8 e2e3",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "c2c4 g8f6 g1f3 e7e6 b1c3 d7d5 d2d4 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "c2c4 g8f6 g1f3 e7e6 g2g3 d7d5 f1g2 f8e7",
+ "c2c4 g8f6 g1f3 g7g6 b1c3 f8g7 e2e4",
+ "c2c4 g8f6 g1f3 g7g6 g2g3 f8g7 f1g2 e8g8",
+ "d2d4 d7d5 c2c4 c7c6 b1c3 g8f6 e2e3",
+ "d2d4 d7d5 c2c4 c7c6 b1c3 g8f6 g1f3 d5c4 a2a4 c8f5 e2e3 e7e6 f1c4",
+ "d2d4 d7d5 c2c4 c7c6 b1c3 g8f6 g1f3 e7e6 c1g5",
+ "d2d4 d7d5 c2c4 c7c6 b1c3 g8f6 g1f3 e7e6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 d7d5 c2c4 c7c6 b1c3 g8f6 g1f3 e7e6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 d7d5 c2c4 c7c6 g1f3 g8f6 b1c3 d5c4 a2a4 c8f5 e2e3 e7e6 f1c4",
+ "d2d4 d7d5 c2c4 c7c6 g1f3 g8f6 b1c3 e7e6 c1g5",
+ "d2d4 d7d5 c2c4 c7c6 g1f3 g8f6 b1c3 e7e6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 d7d5 c2c4 c7c6 g1f3 g8f6 b1c3 e7e6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 d7d5 c2c4 c7c6 g1f3 g8f6 e2e3",
+ "d2d4 d7d5 c2c4 d5c4 g1f3 e7e6 e2e3 g8f6",
+ "d2d4 d7d5 c2c4 d5c4 g1f3 g8f6 e2e3 e7e6 f1c4 c7c5 e1g1 a7a6",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 c7c6",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 f8e7 g1f3 g8f6 c1f4 e8g8 e2e3",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 f8e7 g1f3 g8f6 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 f8e7 g1f3 g8f6 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 c1g5 f8e7 e2e3",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 c4d5 e6d5 c1g5",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 b8d7",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 c7c5",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 c7c6 c1g5",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 f8b4",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 d7d5 c2c4 e7e6 b1c3 g8f6 g1f3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 b8d7",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 c7c5",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 c7c6 c1g5",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 f8b4",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 c1g5",
+ "d2d4 d7d5 c2c4 e7e6 g1f3 g8f6 g2g3",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 b8d7",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 c7c5",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 c7c6 c1g5",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 f8b4",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 c1g5",
+ "d2d4 d7d5 g1f3 e7e6 c2c4 g8f6 g2g3",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 c7c6 b1c3 d5c4 a2a4 c8f5 e2e3 e7e6 f1c4",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 c7c6 b1c3 e7e6 c1g5",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 c7c6 e2e3",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 d5c4 e2e3 e7e6 f1c4 c7c5 e1g1 a7a6",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 b8d7",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 c7c5",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 c7c6 c1g5",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 f8b4",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 c1g5",
+ "d2d4 d7d5 g1f3 g8f6 c2c4 e7e6 g2g3",
+ "d2d4 d7d6 e2e4 g7g6",
+ "d2d4 d7d6 e2e4 g8f6 b1c3 g7g6 f2f4 f8g7 g1f3",
+ "d2d4 e7e6 c2c4 b7b6 g1f3",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 c1g5 f8e7 e2e3",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 c4d5 e6d5 c1g5",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 b8d7",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 c7c5",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 c7c6 c1g5",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 f8b4",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 d7d5 g1f3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 f8b4 d1c2 e8g8",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 f8b4 e2e3 b7b6",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 f8b4 e2e3 c7c5 f1d3",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 f8b4 e2e3 e8g8 f1d3 d7d5 g1f3",
+ "d2d4 e7e6 c2c4 g8f6 b1c3 f8b4 g1f3",
+ "d2d4 e7e6 c2c4 g8f6 c1g5 f8b4",
+ "d2d4 e7e6 c2c4 g8f6 c1g5 h7h6",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 b7b6 a2a3 c8b7 b1c3 d7d5 c4d5 f6d5",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 b7b6 b1c3 c8b7 a2a3 d7d5 c4d5 f6d5",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 b7b6 b1c3 f8b4",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 b7b6 g2g3 c8a6 b2b3 f8b4 c1d2 b4e7",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 b7b6 g2g3 c8b7 f1g2 f8e7 e1g1 e8g8 b1c3 f6e4 d1c2 e4c3 c2c3",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 c7c5 d4d5 e6d5 c4d5 d7d6 b1c3 g7g6",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 b8d7",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 c7c5",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 c7c6 c1g5",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 f8b4",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 c1g5",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 d7d5 g2g3",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 f8b4 b1d2",
+ "d2d4 e7e6 c2c4 g8f6 g1f3 f8b4 c1d2",
+ "d2d4 e7e6 c2c4 g8f6 g2g3 d7d5 f1g2",
+ "d2d4 e7e6 e2e4 d7d5 b1c3 f8b4 e4e5 c7c5 a2a3 b4c3",
+ "d2d4 e7e6 e2e4 d7d5 b1d2 c7c5 g1f3",
+ "d2d4 e7e6 e2e4 d7d5 b1d2 g8f6 e4e5 f6d7 f1d3 c7c5 c2c3 b8c6 g1e2 ",
+ "d2d4 g8f6 c1g5 f6e4 g5f4 c7c5 f2f3 d8a5 c2c3 e4f6 d4d5 a5b6",
+ "d2d4 g8f6 c2c4 c7c5 d4d5 b7b5 c4b5 a7a6",
+ "d2d4 g8f6 c2c4 c7c5 d4d5 e7e6 b1c3 e6d5 c4d5 d7d6",
+ "d2d4 g8f6 c2c4 d7d6 b1c3",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 c1g5 f8e7 e2e3",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 c4d5 e6d5 c1g5",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 b8d7",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 c7c5",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 c7c6 c1g5",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 f8b4",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 d7d5 g1f3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 f8b4 d1c2 e8g8",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 f8b4 e2e3 b7b6",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 f8b4 e2e3 c7c5 f1d3",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 f8b4 e2e3 e8g8 f1d3 d7d5 g1f3",
+ "d2d4 g8f6 c2c4 e7e6 b1c3 f8b4 g1f3",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 b7b6 a2a3 c8b7 b1c3 d7d5 c4d5 f6d5",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 b7b6 b1c3 c8b7 a2a3 d7d5 c4d5 f6d5",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 b7b6 b1c3 f8b4",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 b7b6 g2g3 c8a6 b2b3 f8b4 c1d2 b4e7",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 b7b6 g2g3 c8b7 f1g2 f8e7 e1g1 e8g8 b1c3 f6e4 d1c2 e4c3 c2c3",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 c7c5 d4d5 e6d5 c4d5 d7d6 b1c3 g7g6",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 b8d7",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 c7c5",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 c7c6 c1g5",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 f8b4",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 c1g5",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 d7d5 g2g3",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 f8b4 b1d2",
+ "d2d4 g8f6 c2c4 e7e6 g1f3 f8b4 c1d2",
+ "d2d4 g8f6 c2c4 e7e6 g2g3 d7d5 f1g2",
+ "d2d4 g8f6 c2c4 g7g6 b1c3 d7d5 c4d5 f6d5 e2e4 d5c3 b2c3 f8g7 f1c4",
+ "d2d4 g8f6 c2c4 g7g6 b1c3 d7d5 g1f3 f8g7 d1b3 d5c4 b3c4",
+ "d2d4 g8f6 c2c4 g7g6 b1c3 f8g7 e2e4 d7d6 f1e2 e8g8 c1g5",
+ "d2d4 g8f6 c2c4 g7g6 b1c3 f8g7 e2e4 d7d6 f1e2 e8g8 g1f3 e7e5 e1g1 b8c6 d4d5 c6e7 f3e1 f6d7",
+ "d2d4 g8f6 c2c4 g7g6 b1c3 f8g7 e2e4 d7d6 f2f3 e8g8 c1e3",
+ "d2d4 g8f6 c2c4 g7g6 b1c3 f8g7 e2e4 d7d6 g1f3 e8g8 f1e2 e7e5 e1g1 b8c6 d4d5 c6e7 f3e1 f6d7",
+ "d2d4 g8f6 c2c4 g7g6 g1f3 f8g7 b1c3 e8g8 e2e4 d7d6 f1e2 e7e5 e1g1 b8c6 d4d5 c6e7 f3e1 f6d7",
+ "d2d4 g8f6 c2c4 g7g6 g1f3 f8g7 g2g3 e8g8 f1g2 d7d6 e1g1",
+ "d2d4 g8f6 c2c4 g7g6 g2g3 f8g7 f1g2 e8g8",
+ "d2d4 g8f6 g1f3 c7c5",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 c7c6 b1c3 d5c4 a2a4 c8f5 e2e3 e7e6 f1c4",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 c7c6 b1c3 e7e6 c1g5",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 c7c6 e2e3",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 d5c4 e2e3 e7e6 f1c4 c7c5 e1g1 a7a6",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 b8d7",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 c7c5",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 c7c6 c1g5",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 f8b4",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 c1g5",
+ "d2d4 g8f6 g1f3 d7d5 c2c4 e7e6 g2g3",
+ "d2d4 g8f6 g1f3 e7e6 c1g5",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 b7b6 a2a3 c8b7 b1c3 d7d5 c4d5 f6d5",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 b7b6 b1c3 c8b7 a2a3 d7d5 c4d5 f6d5",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 b7b6 b1c3 f8b4",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 b7b6 g2g3 c8a6 b2b3 f8b4 c1d2 b4e7",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 b7b6 g2g3 c8b7 f1g2 f8e7 e1g1 e8g8 b1c3 f6e4 d1c2 e4c3 c2c3",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 c7c5 d4d5 e6d5 c4d5 d7d6 b1c3 g7g6",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 b8d7",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 c7c5",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 c7c6 c1g5",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 f8b4",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 c1g5",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 d7d5 g2g3",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 f8b4 b1d2",
+ "d2d4 g8f6 g1f3 e7e6 c2c4 f8b4 c1d2",
+ "d2d4 g8f6 g1f3 e7e6 g2g3",
+ "d2d4 g8f6 g1f3 g7g6 c1g5",
+ "d2d4 g8f6 g1f3 g7g6 c2c4 f8g7 b1c3 e8g8 e2e4 d7d6 f1e2 e7e5 e1g1 b8c6 d4d5 c6e7 f3e1 f6d7",
+ "d2d4 g8f6 g1f3 g7g6 c2c4 f8g7 g2g3 e8g8 f1g2 d7d6 e1g1",
+ "d2d4 g8f6 g1f3 g7g6 g2g3 f8g7 f1g2 e8g8",
+ "e2e4 c7c5 b1c3 b8c6 g2g3 g7g6 f1g2 f8g7",
+ "e2e4 c7c5 c2c3 d7d6 g1f3 g8f6",
+ "e2e4 c7c5 c2c3 g8f6 e4e5 f6d5 d2d4 c5d4 g1f3 ",
+ "e2e4 c7c5 c2c3 g8f6 e4e5 f6d5 g1f3",
+ "e2e4 c7c5 d2d3 g8f6",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 e7e6 b1c3 a7a6",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 e7e6 b1c3 d8c7",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 g7g6 b1c3 f8g7 c1e3 g8f6 f1c4",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 g7g6 c2c4 f8g7 f1d3 g8f6 b1c3 ",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 g8f6 b1c3 d7d6 c1g5 e7e6 d1d2 a7a6 e1c1 h7h6",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 g8f6 b1c3 d7d6 c1g5 e7e6 d1d2 f8e7 e1c1 e8g8",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 g8f6 b1c3 d7d6 f1c4",
+ "e2e4 c7c5 g1f3 b8c6 d2d4 c5d4 f3d4 g8f6 b1c3 e7e5 d4b5 d7d6",
+ "e2e4 c7c5 g1f3 b8c6 f1b5",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 a7a6 c1e3",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 a7a6 c1g5 e7e6 f2f4",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 a7a6 f1e2 e7e5 d4b3 f8e7",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 a7a6 f2f4",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 b8c6 c1g5 e7e6 d1d2 a7a6 e1c1 h7h6",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 b8c6 c1g5 e7e6 d1d2 f8e7 e1c1 e8g8",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 b8c6 f1c4",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 e7e6 f1e2",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 e7e6 g2g4",
+ "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 g7g6 c1e3 f8g7 f2f3",
+ "e2e4 c7c5 g1f3 d7d6 f1b5 b8d7",
+ "e2e4 c7c5 g1f3 d7d6 f1b5 c8d7 b5d7",
+ "e2e4 c7c5 g1f3 e7e6 b1c3",
+ "e2e4 c7c5 g1f3 e7e6 d2d4 c5d4 f3d4 a7a6 f1d3",
+ "e2e4 c7c5 g1f3 e7e6 d2d4 c5d4 f3d4 b8c6 b1c3 a7a6",
+ "e2e4 c7c5 g1f3 e7e6 d2d4 c5d4 f3d4 b8c6 b1c3 d8c7",
+ "e2e4 c7c5 g1f3 e7e6 d2d4 c5d4 f3d4 g8f6 b1c3 d7d6 f1e2",
+ "e2e4 c7c5 g1f3 e7e6 d2d4 c5d4 f3d4 g8f6 b1c3 d7d6 g2g4",
+ "e2e4 c7c6 c2c4 d7d5",
+ "e2e4 c7c6 d2d4 d7d5 b1c3 d5e4 c3e4 b8d7",
+ "e2e4 c7c6 d2d4 d7d5 b1c3 d5e4 c3e4 c8f5 e4g3 f5g6 h2h4 h7h6",
+ "e2e4 c7c6 d2d4 d7d5 b1d2 d5e4 d2e4 b8d7",
+ "e2e4 c7c6 d2d4 d7d5 b1d2 d5e4 d2e4 c8f5 e4g3 f5g6 h2h4 h7h6",
+ "e2e4 c7c6 d2d4 d7d5 e4d5 c6d5 c2c4 g8f6 b1c3 e7e6 g1f3",
+ "e2e4 c7c6 d2d4 d7d5 e4e5 c8f5",
+ "e2e4 c7c6 b1c3 d7d5 d2d4 d5e4 c3e4 c8f5 e4g3 f5g6 h2h4 h7h6",
+ "e2e4 c7c6 b1c3 d7d5 g1f3 c8g4 h2h3 g4f3 d1f3 e7e6",
+ "e2e4 c7c6 b1c3 d7d5 g1f3 d5e4 c3e4 g8f6",
+ "e2e4 c7c6 g1f3 d7d5 b1c3",
+ "e2e4 d7d6 d2d4 g7g6",
+ "e2e4 d7d6 d2d4 g8f6 b1c3 g7g6 f2f4 f8g7 g1f3",
+ "e2e4 e7e5 b1c3 g8f6 g1f3 b8c6",
+ "e2e4 e7e5 g1f3 b8c6 b1c3 g8f6 f1b5",
+ "e2e4 e7e5 g1f3 b8c6 d2d4 e5d4 f3d4",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 d7d6",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 g8f6 e1g1 f6e4 d2d4 b7b5 a4b3 d7d5 d4e5 c8e6 c2c3",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 g8f6 e1g1 f8e7 f1e1 b7b5 a4b3 d7d6 c2c3 e8g8 h2h3 c6a5 b3c2 c7c5 d2d4 d8c7 b1d2",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 g8f6 e1g1 f8e7 f1e1 b7b5 a4b3 d7d6 c2c3 e8g8 h2h3 c6b8 d2d4 b8d7",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 g8f6 e1g1 f8e7 f1e1 b7b5 a4b3 d7d6 c2c3 e8g8 h2h3 c8b7 d2d4 f8e8",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 g8f6 e1g1 f8e7 f1e1 b7b5 a4b3 e8g8 c2c3 d7d6 h2h3 c6a5 b3c2 c7c5 d2d4 d8c7 b1d2",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 g8f6 e1g1 f8e7 f1e1 b7b5 a4b3 e8g8 c2c3 d7d6 h2h3 c6b8 d2d4 b8d7",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5a4 g8f6 e1g1 f8e7 f1e1 b7b5 a4b3 e8g8 c2c3 d7d6 h2h3 c8b7 d2d4 f8e8",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 a7a6 b5c6 d7c6 e1g1",
+ "e2e4 e7e5 g1f3 b8c6 f1b5 g8f6 e1g1",
+ "e2e4 e7e5 g1f3 b8c6 f1c4 f8c5",
+ "e2e4 e7e5 g1f3 b8c6 f1c4 g8f6",
+ "e2e4 e7e5 g1f3 g8f6 f3e5 d7d6 e5f3 f6e4 d2d4",
+ "e2e4 e7e6 d2d4 d7d5 b1c3 f8b4 e4e5 c7c5 a2a3 b4c3 b2c3 g8e7",
+ "e2e4 e7e6 d2d4 d7d5 b1c3 g8f6 c1g5",
+ "e2e4 e7e6 d2d4 d7d5 b1d2 c7c5 e4d5 e6d5",
+ "e2e4 e7e6 d2d4 d7d5 b1d2 c7c5 g1f3",
+ "e2e4 e7e6 d2d4 d7d5 b1d2 g8f6 e4e5",
+ "e2e4 e7e6 d2d4 d7d5 e4e5 c7c5 c2c3 b8c6 g1f3 d8b6 a2a3 ",
+ "e2e4 e7e6 d2d4 d7d5 e4e5 c7c5 c2c3 d8b6 g1f3 b8c6 a2a3",
+ "e2e4 g7g6 d2d4 f8g7 b1c3 c7c6 g1f3",
+ "e2e4 g7g6 d2d4 f8g7 b1c3 d7d6 c1e3",
+ "e2e4 g7g6 d2d4 f8g7 b1c3 d7d6 g1f3",
+ "e2e4 g8f6 e4e5 f6d5 c2c4 d5b6 d2d4 d7d6 e5d6 e7d6",
+ "e2e4 g8f6 e4e5 f6d5 d2d4 d7d6 g1f3",
+ "g1f3 c7c5 c2c4 b8c6",
+ "g1f3 c7c5 c2c4 g8f6 b1c3 b8c6",
+ "g1f3 c7c5 c2c4 g8f6 b1c3 e7e6 g2g3 b7b6 f1g2 c8b7 e1g1 f8e7",
+ "g1f3 c7c5 c2c4 g8f6 g2g3",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 c7c6 b1c3 d5c4 a2a4 c8f5 e2e3 e7e6 f1c4",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 c7c6 b1c3 e7e6 c1g5",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 d1c2 f8d6",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 c7c6 e2e3",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 d5c4 e2e3 e7e6 f1c4 c7c5 e1g1 a7a6",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 b8d7",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 c7c5",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 c7c6 c1g5",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 f8b4",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 c1g5",
+ "g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3",
+ "g1f3 d7d5 g2g3",
+ "g1f3 g8f6 c2c4 b7b6 g2g3",
+ "g1f3 g8f6 c2c4 c7c5 b1c3 b8c6",
+ "g1f3 g8f6 c2c4 c7c5 b1c3 e7e6 g2g3 b7b6 f1g2 c8b7 e1g1 f8e7",
+ "g1f3 g8f6 c2c4 c7c5 g2g3",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 b8d7",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 c7c5",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 c7c6 c1g5",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 f8b4",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 f8e7 c1f4 e8g8 e2e3",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "g1f3 g8f6 c2c4 e7e6 b1c3 d7d5 d2d4 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "g1f3 g8f6 c2c4 e7e6 g2g3 d7d5 f1g2 f8e7",
+ "g1f3 g8f6 c2c4 g7g6 b1c3 f8g7 e2e4",
+ "g1f3 g8f6 c2c4 g7g6 g2g3 f8g7 f1g2 e8g8",
+ "g1f3 g8f6 d2d4 c7c5",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 c7c6 b1c3 d5c4 a2a4 c8f5 e2e3 e7e6 f1c4",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 c7c6 b1c3 e7e6 c1g5",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 d1c2 f8d6",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 c7c6 b1c3 e7e6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 c7c6 e2e3",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 d5c4 e2e3 e7e6 f1c4 c7c5 e1g1 a7a6",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 b8d7",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 c7c5",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 c7c6 c1g5",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 f8b4",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 c1g5",
+ "g1f3 g8f6 d2d4 d7d5 c2c4 e7e6 g2g3",
+ "g1f3 g8f6 d2d4 e7e6 c1g5",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 b7b6 a2a3 c8b7 b1c3 d7d5 c4d5 f6d5",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 b7b6 b1c3 c8b7 a2a3 d7d5 c4d5 f6d5",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 b7b6 b1c3 f8b4",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 b7b6 g2g3 c8a6 b2b3 f8b4 c1d2 b4e7",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 b7b6 g2g3 c8b7 f1g2 f8e7 e1g1 e8g8 b1c3 f6e4 d1c2 e4c3 c2c3",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 c7c5 d4d5 e6d5 c4d5 d7d6 b1c3 g7g6",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 b8d7",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 c7c5",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 c7c6 c1g5",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 c7c6 e2e3 b8d7 d1c2 f8d6",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 c7c6 e2e3 b8d7 f1d3 d5c4 d3c4 b7b5 c4d3",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 f8b4",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 f8e7 c1f4 e8g8 e2e3",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 f8e7 c1g5 e8g8 e2e3 h7h6",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 b1c3 f8e7 c1g5 h7h6 g5h4 e8g8 e2e3 b7b6",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 c1g5",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 d7d5 g2g3",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 f8b4 b1d2",
+ "g1f3 g8f6 d2d4 e7e6 c2c4 f8b4 c1d2",
+ "g1f3 g8f6 d2d4 e7e6 g2g3",
+ "g1f3 g8f6 d2d4 g7g6 c1g5",
+ "g1f3 g8f6 d2d4 g7g6 c2c4 f8g7 b1c3 e8g8 e2e4 d7d6 f1e2 e7e5 e1g1 b8c6 d4d5 c6e7 f3e1 f6d7",
+ "g1f3 g8f6 d2d4 g7g6 c2c4 f8g7 g2g3 e8g8 f1g2 d7d6 e1g1",
+ "g1f3 g8f6 d2d4 g7g6 g2g3 f8g7 f1g2 e8g8",
+ "g1f3 g8f6 g2g3 g7g6",
+};
+
+// Returns bool. If true, then book[start] to book[end-1] inclusive will
+// match line. So end-start is the number of matching lines.
+int book_range(char *line, int *startp, int *endp)
+{
+ unsigned int start, end;
+ if (ARRAY_SIZE(book) == 0) return 0; // no book??
+ /* Find start. */
+ for (start = 0; start < ARRAY_SIZE(book); start++) {
+ int result = strncmp(book[start], line, strlen(line));
+ if (result < 0)
+ continue; // not yet
+ else if (result > 0)
+ break; // line not in book at all
+ // OK, found start.
+ for (end = start + 1; end < ARRAY_SIZE(book); end++) {
+ int result = strncmp(book[end], line, strlen(line));
+ if (result > 0)
+ break;
+ else
+ assert(result == 0 && "opening book not sorted :(");
+ }
+ // Found end.
+ *startp = start;
+ *endp = end;
+ return 1;
+ }
+ return 0; // line not found
+}
+
+int book_enabled = 1;
+
+/**
+ * Get a move from the book. Line is a string like "e2e4 e7e5 g1f3 " - note
+ * the space at the end! and the board is for passing to move_islegal.
+ */
+move_t book_move(char *line, board_t *board)
+{
+ int start, end;
+ if (!book_enabled) return 0;
+ if (book_range(line, &start, &end)) {
+ char book_move_str[BOOK_MOVE_LENGTH+1];
+ move_t book_move;
+ unsigned long move_index;
+ static int rand_inited = 0;
+ char *errmsg;
+ if (!rand_inited) {
+ sgenrand((unsigned long)get_ticks());
+ rand_inited = 1;
+ }
+ assert(end - start > 0);
+ move_index = (genrand() % (end-start)) + start;
+ strncpy(book_move_str, &book[move_index][strlen(line)],
+ BOOK_MOVE_LENGTH);
+ book_move_str[BOOK_MOVE_LENGTH] = 0;
+ book_move = move_islegal(board, book_move_str, &errmsg);
+ if (!book_move) {
+ set_cursor_pos(0,0);
+ printf("BUG: please email bblum@cs.cmu.edu the following: \n");
+ printf("Line: \"%s\"\n", line);
+ printf("Attempted book line: \"%s\"\n", book[move_index]);
+ printf("Attempted move: \"%s\"\n", book_move_str);
+ assert(0 && "Illegal line in opening book?");
+ }
+ return book_move;
+ } else {
+ return 0;
+ }
+}
+/****************************************************************************
+ * engine.c - wrapper functions for managing computer vs human play
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+#define ENGINE_REPEATED_BUCKETS 127
+
+/* from xboard.c, for printing */
+// void output(char *);
+
+/**
+ * Initialize a game engine given the searching function, with a new board
+ */
+engine_t *engine_init(search_fn search)
+{
+ engine_t *e = malloc(sizeof(engine_t));
+ affirm_msg(e, "Couldn't allocate game engine");
+ e->board = board_init();
+ e->search = search;
+ e->line[0] = '\0';
+ e->line_moves = 0;
+ e->inbook = 1;
+ return e;
+}
+
+#define SEARCHTIME_DEFAULT 5
+#define SEARCHTIME_MAX 60
+unsigned int searchtime = SEARCHTIME_DEFAULT;
+
+extern int outbuf_size;
+extern int text_loud;
+extern char outbuf[];
+void output();
+
+/**
+ * Have the engine generate a move for the side to play. String must be freed.
+ */
+char *engine_generatemove(engine_t *e)
+{
+ if (e->inbook)
+ {
+ move_t move = book_move(e->line, e->board);
+ if (move)
+ {
+ /* book lookup was successful */
+ // output("ENGINE: Book lookup successful");
+ char *str = move_tostring(move);
+ if (text_loud) {
+ snprintf(outbuf, outbuf_size,
+ "My move: %s (from opening book)", str);
+ output();
+ }
+ return str;
+ }
+ else
+ {
+ /* we've left the book lines */
+ // output("ENGINE: Leaving opening book lines");
+ e->inbook = 0;
+ }
+ }
+ /* we get here if already out of book or if we just left book */
+ return move_tostring(e->search(e->board, searchtime, NULL, NULL));
+}
+
+/**
+ * Change the board to reflect a move being made. Returns 1 if the move is
+ * illegal, 0 if it's good
+ */
+int engine_applymove(engine_t *e, char *str, char **errmsg)
+{
+ /* we need to make the move before adding, else we won't detect draws
+ * before they actually are called */
+ move_t move = move_islegal(e->board, str, errmsg);
+ if (move == 0) {
+ return 0;
+ }
+ /* keep track of the game's line, but only if not too long */
+ if (strlen(e->line) < BOOK_LINE_MAX_LENGTH-6) {
+ strcat(e->line, str);
+ strcat(e->line, " ");
+ assert(e->line_moves == e->board->moves);
+ e->line_moves++;
+ }
+
+ board_applymove(e->board, move);
+
+ return 1;
+}
+
+void engine_undomove(engine_t *e)
+{
+ assert(e->board->moves > 0);
+ if (e->line_moves == e->board->moves) {
+ int i = strlen(e->line)-1;
+ assert(i > 0);
+ assert(e->line[i] == ' ');
+ if (e->line_moves == 1) {
+ e->line[0] = 0;
+ } else {
+ for (i--; i > 0 && e->line[i] != ' '; i--) { continue; }
+ assert(i > 0);
+ e->line[i+1] = 0;
+ }
+ e->line_moves--;
+ }
+ e->inbook = 1; // Not necessarily true. But it can't hurt.
+ board_undomove(e->board, e->board->history[e->board->moves-1].move);
+}
+
+void engine_destroy(engine_t *e)
+{
+ if (e == NULL)
+ {
+ return;
+ }
+ board_destroy(e->board);
+ free(e);
+ return;
+}
+/****************************************************************************
+ * eval.c - evaluation function to tell how good a position is
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+/* endgame starts when both sides have <= LIM_ENDGAME */
+#define EVAL_LIM_ENDGAME 1600
+/* use this limit when no queens on the board */
+#define EVAL_LIM_ENDGAME2 2000
+
+#define EVAL_CASTLE_BONUS 20
+
+int16_t eval_piecevalue[6] = { 100, 300, 300, 500, 900, 0 };
+int16_t eval_piecevalue_endgame[6] = { 125, 300, 300, 550, 1200, 0 };
+
+/* Players get small point bonuses if their pieces are on good squares. If
+ * white has a rook on d1, squarevalue[WHITE][ROOK][D1] will be added to
+ * white's score. */
+/* Differences between src/dest squares are considered when ordering moves, so
+ * it is important that for any legal (src,dest) pair, abs(sqval(dest) -
+ * sqval(src)) <= SOME_CONSTANT - that constant is 16 for now. (only in the
+ * regular tables, not the endgame tables) */
+int16_t eval_squarevalue[2][6][64] = {
+ /********************************************************************
+ * WHITE
+ ********************************************************************/
+ {
+ /* PAWN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, -4, -4, 4, 0, 0,
+ 6, 2, 3, 4, 4, 3, 2, 8,
+ 3, 4, 12, 12, 12, 8, 4, 3,
+ 5, 8, 16, 20, 20, 16, 8, 5,
+ 20, 24, 24, 32, 32, 24, 24, 20,
+ 36, 36, 40, 40, 40, 40, 36, 36,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KNIGHT */
+ {
+ -10, -6, -6, -6, -6, -6, -6,-10,
+ -6, 0, 0, 3, 3, 0, 0, -6,
+ -6, 0, 8, 4, 4, 10, 0, -6,
+ -6, 0, 8, 10, 10, 8, 0, -6,
+ -4, 0, 8, 10, 10, 8, 0, -4,
+ -4, 5, 12, 12, 12, 12, 5, -4,
+ -4, 0, 5, 3, 3, 5, 0, -4,
+ -10, -4, -4, -4, -4, -4, -4,-10
+ },
+ /* BISHOP */
+ {
+ -6, -5, -5, -5, -5, -5, -5, -6,
+ -5, 10, 5, 8, 8, 5, 10, -5,
+ -5, 5, 3, 5, 5, 3, 5, -5,
+ -5, 3, 10, 3, 3, 10, 3, -5,
+ -5, 5, 10, 3, 3, 10, 5, -5,
+ -5, 3, 8, 8, 8, 8, 3, -5,
+ -5, 5, 5, 8, 8, 5, 5, -5,
+ -6, -5, -5, -5, -5, -5, -5, -6
+ },
+ /* ROOK */
+ {
+ 0, 3, 3, 3, 3, 3, 3, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 2, 2, 2, 1, 0,
+ 3, 5, 8, 8, 8, 8, 5, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* QUEEN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KING */
+ {
+ 5, 5, 8, 0, 0, -5, 10, 10,
+ 0, 0, 0, 0, 0, 0, 5, 5,
+ 0, 0, 0, -5, -5, 0, 0, 0,
+ 0, 0, -5,-10,-10, -5, 0, 0,
+ 0, -5,-10,-10,-10,-10, -5, 0,
+ -5,-10,-10,-15,-15,-10,-10, -5,
+ -20,-20,-20,-20,-20,-20,-20,-20,
+ -20,-20,-20,-20,-20,-20,-20,-20
+ }
+ },
+ /********************************************************************
+ * BLACK
+ ********************************************************************/
+ {
+ /* PAWN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 36, 36, 40, 40, 40, 40, 36, 36,
+ 20, 24, 24, 32, 32, 24, 24, 20,
+ 5, 8, 16, 20, 20, 16, 8, 5,
+ 3, 4, 12, 12, 12, 8, 4, 3,
+ 6, 2, 3, 4, 4, 3, 2, 8,
+ 0, 0, 0, -4, -4, 4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KNIGHT */
+ {
+ -10, -4, -4, -4, -4, -4, -4,-10,
+ -4, 0, 5, 3, 3, 5, 0, -4,
+ -4, 5, 12, 12, 12, 12, 5, -4,
+ -4, 0, 8, 10, 10, 8, 0, -4,
+ -6, 0, 8, 10, 10, 8, 0, -6,
+ -6, 0, 8, 4, 4, 10, 0, -6,
+ -6, 0, 0, 3, 3, 0, 0, -6,
+ -10, -6, -6, -6, -6, -6, -6,-10
+ },
+ /* BISHOP */
+ {
+ -6, -5, -5, -5, -5, -5, -5, -6,
+ -5, 5, 5, 8, 8, 5, 5, -5,
+ -5, 5, 8, 8, 8, 8, 5, -5,
+ -5, 3, 10, 5, 5, 10, 3, -5,
+ -5, 5, 10, 5, 5, 10, 5, -5,
+ -5, 3, 3, 5, 5, 3, 3, -5,
+ -5, 10, 5, 8, 8, 5, 10, -5,
+ -6, -5, -5, -5, -5, -5, -5, -6
+ },
+ /* ROOK */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 5, 8, 8, 8, 8, 5, 3,
+ 0, 1, 2, 2, 2, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 3, 3, 3, 3, 3, 3, 0
+ },
+ /* QUEEN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KING */
+ {
+ -20,-20,-20,-20,-20,-20,-20,-20,
+ -20,-20,-20,-20,-20,-20,-20,-20,
+ -5,-10,-10,-15,-15,-10,-10, -5,
+ 0, -5,-10,-10,-10,-10, -5, 0,
+ 0, 0, -5,-10,-10, -5, 0, 0,
+ 0, 0, 0, -5, -5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 5, 5,
+ 5, 5, 8, 0, 0, -5, 10, 10
+ }
+ }
+};
+int16_t eval_squarevalue_endgame[2][6][64] = {
+ /********************************************************************
+ * WHITE
+ ********************************************************************/
+ {
+ /* PAWN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ -10,-10,-10,-10,-10,-10,-10,-10,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 20, 20, 20, 20, 20, 20, 20, 20,
+ 40, 40, 40, 40, 40, 40, 40, 40,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KNIGHT */
+ {
+ -10, -5, -5, -5, -5, -5, -5,-10,
+ -8, 0, 0, 3, 3, 0, 0, -8,
+ -8, 0, 10, 8, 8, 10, 0, -8,
+ -8, 0, 8, 10, 10, 8, 0, -8,
+ -8, 0, 8, 10, 10, 8, 0, -8,
+ -8, 0, 12, 12, 12, 12, 0, -8,
+ -8, 0, 9, 3, 3, 9, 0, -8,
+ -10, -5, -5, -5, -5, -5, -5,-10
+ },
+ /* BISHOP */
+ {
+ -8, -5, -5, -5, -5, -5, -5, -8,
+ -5, 3, 5, 5, 5, 5, 3, -5,
+ -5, 5, 5, 8, 8, 5, 5, -5,
+ -5, 5, 10, 10, 10, 10, 5, -5,
+ -5, 5, 10, 10, 10, 10, 5, -5,
+ -5, 3, 8, 8, 8, 8, 3, -5,
+ -5, 3, 5, 8, 8, 5, 3, -5,
+ -8, -5, -5, -5, -5, -5, -5, -8
+ },
+ /* ROOK */
+ {
+ 0, 3, 3, 5, 5, 3, 3, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 2, 2, 2, 1, 0,
+ 1, 3, 5, 5, 5, 5, 3, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* QUEEN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KING */
+ {
+ -25,-15,-10,-10,-10,-10,-15,-25,
+ -15, -5, 0, 0, 0, 0, -5,-15,
+ -10, 0, 5, 10, 10, 5, 0,-10,
+ -10, 0, 10, 15, 15, 10, 0,-10,
+ -5, 5, 15, 20, 20, 15, 5, -5,
+ 0, 10, 20, 20, 20, 15, 10, 0,
+ -15, 0, 5, 5, 5, 5, 0,-15,
+ -25,-15,-10,-10,-10,-10,-15,-25
+ }
+ },
+ /********************************************************************
+ * BLACK
+ ********************************************************************/
+ {
+ /* PAWN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 40, 40, 40, 40, 40, 40, 40, 40,
+ 20, 20, 20, 20, 20, 20, 20, 20,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ -10,-10,-10,-10,-10,-10,-10,-10,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KNIGHT */
+ {
+ -10, -5, -5, -5, -5, -5, -5,-10,
+ -8, 0, 9, 3, 3, 9, 0, -8,
+ -8, 0, 12, 12, 12, 12, 0, -8,
+ -8, 0, 8, 10, 10, 8, 0, -8,
+ -8, 0, 8, 10, 10, 8, 0, -8,
+ -8, 0, 10, 8, 8, 10, 0, -8,
+ -8, 0, 0, 3, 3, 0, 0, -8,
+ -10, -5, -5, -5, -5, -5, -5,-10
+ },
+ /* BISHOP */
+ {
+ -8, -5, -5, -5, -5, -5, -5, -8,
+ -5, 3, 5, 8, 8, 5, 3, -5,
+ -5, 3, 8, 8, 8, 8, 3, -5,
+ -5, 5, 10, 10, 10, 10, 5, -5,
+ -5, 5, 10, 10, 10, 10, 5, -5,
+ -5, 5, 5, 8, 8, 5, 5, -5,
+ -5, 3, 5, 5, 5, 5, 3, -5,
+ -8, -5, -5, -5, -5, -5, -5, -8
+ },
+ /* ROOK */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 3, 5, 5, 5, 5, 3, 1,
+ 0, 1, 2, 2, 2, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 1, 2, 3, 3, 2, 1, 0,
+ 0, 3, 3, 5, 5, 3, 3, 0
+ },
+ /* QUEEN */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ /* KING */
+ {
+ -25,-15,-10,-10,-10,-10,-15,-25
+ -15, 0, 5, 5, 5, 5, 0,-15,
+ 0, 10, 20, 20, 20, 15, 10, 0,
+ -5, 5, 15, 20, 20, 15, 5, -5,
+ -10, 0, 10, 15, 15, 10, 0,-10,
+ -10, 0, 5, 10, 10, 5, 0,-10,
+ -15, -5, 0, 0, 0, 0, -5,-15,
+ -25,-15,-10,-10,-10,-10,-15,-25,
+ }
+ }
+};
+
+static int16_t eval_endgame(board_t *);
+
+/* Penalty for trapping the d- e- pawns on 2nd rank, or c-pawn with the knight
+ * if there's a pawn on d4 and no pawn on e4 */
+#define EVAL_BLOCKED_PAWN -25
+/* used for pawn-block checking N on c3 with pawns c2 d4 !e4 */
+#define BB_C2D4 (BB_SQUARE(C2) | BB_SQUARE(D4))
+#define BB_C2D4E4 (BB_C2D4 | BB_SQUARE(E4))
+#define BB_C7D5 (BB_SQUARE(C7) | BB_SQUARE(D5))
+#define BB_C7D5E5 (BB_C7D5 | BB_SQUARE(E5))
+/* reward the bishop pair and penalize the knight pair */
+#define EVAL_BISHOP_PAIR 20
+#define EVAL_KNIGHT_PAIR -20
+/* Rooks like to see towards the other end of the board */
+#define EVAL_ROOK_OPENFILE 10
+#define EVAL_ROOK_OPENFILE_MULTIPLIER 3
+/* bonus for having multiple rooks on the 7th - take the number of heavies
+ * on the 7th, leftshift this constant by that number */
+#define EVAL_ROOK_RANK7_MULTIPLIER 12
+/* bonus for having a minor piece on an "outpost" - a hole in the opp's pawn
+ * structure protected by one of own pawns. */
+#define EVAL_OUTPOST_BONUS 32
+
+/**************
+ * King safety
+ **************/
+/* Points for having N pawns on rank 2/3 in front of a castled king*/
+static int16_t pawncover_rank2[4] = { -80, -40, 0, 5 };
+static int16_t pawncover_rank3[4] = { 0, 5, 20, 40 };
+/* penalty for having no pawns on king's file */
+#define EVAL_KINGFILEOPEN -35
+/* penalty for having no pawns on file adjacent to king's file */
+#define EVAL_ADJACENTFILEOPEN -15
+
+/* tropism bonus from one square to another (one square has a piece of given
+ * type on it, the other has the enemy king) */
+#define EVAL_TROPISM_MAX 192
+/* this lookup array gives shiftamounts for distance so we don't have to idiv
+ * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */
+static int tropism_rice[15] = { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5};
+/* this lookup array gives shiftamounts for scaling by piece value
+ * P N B R Q K */
+static int tropism_piecescale[6] = { 3, 2, 2, 1, 0, 0 };
+
+static int16_t tropism(square_t a, square_t b, piece_t piece)
+{
+ int16_t rowdist, coldist;
+ /* absolute values of the difference between the two squares */
+ rowdist = ROW(a) - ROW(b);
+ if (rowdist < 0) { rowdist = -rowdist; }
+ coldist = COL(a) - COL(b);
+ if (coldist < 0) { coldist = -coldist; }
+ /* score inversely proportional to distance, also scaled by how
+ * heavy the piece is - queen right up against the opp king will
+ * get like 100 points */
+ return (EVAL_TROPISM_MAX >> tropism_rice[rowdist + coldist]) >>
+ tropism_piecescale[piece];
+}
+
+int eval_isendgame(board_t *board)
+{
+ if (board->pos[WHITE][QUEEN] | board->pos[BLACK][QUEEN])
+ {
+ return (board->material[WHITE] <= EVAL_LIM_ENDGAME) ||
+ (board->material[BLACK] <= EVAL_LIM_ENDGAME);
+ }
+ return (board->material[WHITE] <= EVAL_LIM_ENDGAME2) ||
+ (board->material[BLACK] <= EVAL_LIM_ENDGAME2);
+}
+
+/**
+ * Evaluate - return a score for the given position for who's to move
+ */
+int16_t eval(board_t *board)
+{
+ int piece, square;
+ bitboard_t piecepos;
+ /* keeps track of {WHITE,BLACK}s score */
+ int16_t score_white, score_black;
+ /* king safety scores - scaled by the material on the board to
+ * encourage trading when under attack */
+ int16_t ksafety_white, ksafety_black;
+ square_t kingsq_white, kingsq_black; /* where's each king */
+ /* counting pieces/pawns for king safety */
+ int num_pieces;
+ /* holes in <color>'s pawnstructure */
+ bitboard_t holes_white, holes_black;
+
+ /* use the special endgame evaluator if in the endgame */
+ if (eval_isendgame(board))
+ {
+ return eval_endgame(board);
+ }
+
+ /* begin evaluating */
+ score_white = 0; score_black = 0;
+ ksafety_white = 0; ksafety_black = 0;
+ kingsq_white = BITSCAN(board->pos[WHITE][KING]);
+ kingsq_black = BITSCAN(board->pos[BLACK][KING]);
+
+ /********************************************************************
+ * Piece/square tables
+ ********************************************************************/
+ /********
+ * White
+ ********/
+ /* regular pieces - pawns taken care of in pawnstructure eval */
+ for (piece = 1; piece < 5; piece++)
+ {
+ piecepos = board->pos[WHITE][piece];
+ while (piecepos)
+ {
+ square = BITSCAN(piecepos);
+ piecepos ^= BB_SQUARE(square);
+ score_white += eval_squarevalue[WHITE][piece][square];
+ /* tropism scores - how close is to our/opp king? */
+ //ksafety_white += tropism(square, kingsq_white, piece);
+ ksafety_black -= tropism(square, kingsq_black, piece);
+ /* Rooks like open files */
+ if (piece == ROOK)
+ {
+ /* no pawns on this file */
+ if (!(board->pos[WHITE][PAWN] & BB_FILE(COL(square))))
+ {
+ score_white += EVAL_ROOK_OPENFILE;
+ }
+ /* how far can we see? */
+ score_white += EVAL_ROOK_OPENFILE_MULTIPLIER * POPCOUNT(colattacks[(board->occupied90 >> (8 * COL(square))) & 0xFF][ROW(square)]);
+ }
+ }
+ }
+ /* king */
+ score_white += eval_squarevalue[WHITE][KING][kingsq_white];
+
+ /********
+ * Black
+ ********/
+ for (piece = 1; piece < 5; piece++)
+ {
+ piecepos = board->pos[BLACK][piece];
+ while (piecepos)
+ {
+ square = BITSCAN(piecepos);
+ piecepos ^= BB_SQUARE(square);
+ score_black += eval_squarevalue[BLACK][piece][square];
+ /* tropism scores - how close is to our/opp king? */
+ ksafety_white -= tropism(square, kingsq_white, piece);
+ //ksafety_black += tropism(square, kingsq_black, piece);
+ /* Rooks like open files */
+ if (piece == ROOK)
+ {
+ /* no pawns on this file */
+ if (!(board->pos[BLACK][PAWN] & BB_FILE(COL(square))))
+ {
+ score_black += EVAL_ROOK_OPENFILE;
+ }
+ /* how far can we see? */
+ score_black += EVAL_ROOK_OPENFILE_MULTIPLIER * POPCOUNT(colattacks[(board->occupied90 >> (8 * COL(square))) & 0xFF][ROW(square)]);
+ }
+ }
+ }
+ /* king */
+ score_black += eval_squarevalue[BLACK][KING][kingsq_white];
+
+ /********************************************************************
+ * Misc. bonuses
+ ********************************************************************/
+ /* bishop/knight pair bonus/penalties */
+ if (POPCOUNT(board->pos[WHITE][BISHOP]) > 1) { score_white += EVAL_BISHOP_PAIR; }
+ if (POPCOUNT(board->pos[WHITE][KNIGHT]) > 1) { score_white += EVAL_KNIGHT_PAIR; }
+ if (POPCOUNT(board->pos[BLACK][BISHOP]) > 1) { score_black += EVAL_BISHOP_PAIR; }
+ if (POPCOUNT(board->pos[BLACK][KNIGHT]) > 1) { score_black += EVAL_KNIGHT_PAIR; }
+ /* pawnstructure bonus */
+ score_white += eval_pawnstructure(board, WHITE, &holes_white);
+ score_black += eval_pawnstructure(board, BLACK, &holes_black);
+ /* analysis of pawnstructure holes - all holes that our pawns attack
+ * and have a minor piece on them get an "outpost" bonus - don't allow
+ * bonus for outposts on the A and H files */
+ /* find white's outposts */
+ holes_black &= board_pawnattacks(board->pos[WHITE][PAWN], WHITE) &
+ (board->pos[WHITE][KNIGHT] | board->pos[WHITE][BISHOP]) &
+ ~(BB_FILEA | BB_FILEH);
+ score_white += EVAL_OUTPOST_BONUS * POPCOUNT(holes_black);
+ /* find black's outposts */
+ holes_white &= board_pawnattacks(board->pos[BLACK][PAWN], BLACK) &
+ (board->pos[BLACK][KNIGHT] | board->pos[BLACK][BISHOP]) &
+ ~(BB_FILEA | BB_FILEH);
+ score_black += EVAL_OUTPOST_BONUS * POPCOUNT(holes_white);
+ /* pawn block penalties */
+ if (((board->piecesofcolor[WHITE] ^ board->pos[WHITE][PAWN]) & BB_SQUARE(D3)) &&
+ (board->pos[WHITE][PAWN] & BB_SQUARE(D2))) /* blocked on D2 */
+ {
+ score_white += EVAL_BLOCKED_PAWN;
+ }
+ if (((board->piecesofcolor[WHITE] ^ board->pos[WHITE][PAWN]) & BB_SQUARE(E3)) &&
+ (board->pos[WHITE][PAWN] & BB_SQUARE(E2))) /* blocked on E2 */
+ {
+ score_white += EVAL_BLOCKED_PAWN;
+ }
+ if ((board->pos[WHITE][KNIGHT] & BB_SQUARE(C3)) && /* knight on C3 */
+ !((board->pos[WHITE][PAWN] ^ BB_C2D4) & BB_C2D4E4)) /* "closed" opening */
+ {
+ score_white += EVAL_BLOCKED_PAWN;
+ }
+ /* black */
+ if (((board->piecesofcolor[BLACK] ^ board->pos[BLACK][PAWN]) & BB_SQUARE(D6)) &&
+ (board->pos[BLACK][PAWN] & BB_SQUARE(D7))) /* blocked on D7 */
+ {
+ score_black += EVAL_BLOCKED_PAWN;
+ }
+ if (((board->piecesofcolor[BLACK] ^ board->pos[BLACK][PAWN]) & BB_SQUARE(E6)) &&
+ (board->pos[BLACK][PAWN] & BB_SQUARE(E7))) /* blocked on E7 */
+ {
+ score_black += EVAL_BLOCKED_PAWN;
+ }
+ if ((board->pos[BLACK][KNIGHT] & BB_SQUARE(C6)) && /* knight on C6 */
+ !((board->pos[BLACK][PAWN] ^ BB_C7D5) & BB_C7D5E5)) /* "closed" defense */
+ {
+ score_black += EVAL_BLOCKED_PAWN;
+ }
+ /* rook/queen on the 7th bonus */
+ score_white += EVAL_ROOK_RANK7_MULTIPLIER <<
+ POPCOUNT((board->pos[WHITE][ROOK] | board->pos[WHITE][QUEEN]) &
+ BB_RANK7);
+ score_black += EVAL_ROOK_RANK7_MULTIPLIER <<
+ POPCOUNT((board->pos[BLACK][ROOK] | board->pos[BLACK][QUEEN]) &
+ BB_RANK2);
+
+ /********************************************************************
+ * King safety - white
+ ********************************************************************/
+ /* pawn shield */
+ if (board->hascastled[WHITE])
+ {
+ ksafety_white += EVAL_CASTLE_BONUS;
+ /* pawn shield one row in front of the king */
+ num_pieces = POPCOUNT(kingattacks[kingsq_white] &
+ board->pos[WHITE][PAWN] & BB_RANK2);
+ ksafety_white += pawncover_rank2[num_pieces];
+ /* pawn shield two rows in front of the king */
+ num_pieces = POPCOUNT(kingattacks[kingsq_white + 8] &
+ board->pos[WHITE][PAWN] & BB_RANK3);
+ ksafety_white += pawncover_rank3[num_pieces];
+ }
+ /* open files near the king */
+ if (!(board->pos[WHITE][PAWN] & BB_FILE(COL(kingsq_white))))
+ {
+ ksafety_white += EVAL_KINGFILEOPEN;
+ }
+ switch(COL(kingsq_white)) /* this idea taken from gnuchess */
+ {
+ case COL_A:
+ case COL_E:
+ case COL_F:
+ case COL_G:
+ if (!(board->pos[WHITE][PAWN] & BB_FILE(COL(kingsq_white) + 1)))
+ {
+ ksafety_white += EVAL_ADJACENTFILEOPEN;
+ }
+ break;
+ case COL_H:
+ case COL_D:
+ case COL_C:
+ case COL_B:
+ if (!(board->pos[WHITE][PAWN] & BB_FILE(COL(kingsq_white) - 1)))
+ {
+ ksafety_white += EVAL_ADJACENTFILEOPEN;
+ }
+ break;
+ default:
+ break;
+ }
+ score_white += ksafety_white * board->material[BLACK] / 3100;
+ /********************************************************************
+ * King safety - black
+ ********************************************************************/
+ /* pawn shield */
+ if (board->hascastled[BLACK])
+ {
+ ksafety_black += EVAL_CASTLE_BONUS;
+ /* pawn shield one row in front of the king */
+ num_pieces = POPCOUNT(kingattacks[kingsq_black] &
+ board->pos[BLACK][PAWN] & BB_RANK7);
+ ksafety_black += pawncover_rank2[num_pieces];
+ /* pawn shield two rows in front of the king */
+ num_pieces = POPCOUNT(kingattacks[kingsq_black - 8] &
+ board->pos[BLACK][PAWN] & BB_RANK6);
+ ksafety_black += pawncover_rank3[num_pieces];
+ }
+ /* open files near the king */
+ if (!(board->pos[BLACK][PAWN] & BB_FILE(COL(kingsq_black))))
+ {
+ ksafety_black += EVAL_KINGFILEOPEN;
+ }
+ switch(COL(kingsq_black)) /* this idea taken from gnuchess */
+ {
+ case COL_A:
+ case COL_E:
+ case COL_F:
+ case COL_G:
+ if (!(board->pos[BLACK][PAWN] & BB_FILE(COL(kingsq_black) + 1)))
+ {
+ ksafety_black += EVAL_ADJACENTFILEOPEN;
+ }
+ break;
+ case COL_H:
+ case COL_D:
+ case COL_C:
+ case COL_B:
+ if (!(board->pos[BLACK][PAWN] & BB_FILE(COL(kingsq_black) - 1)))
+ {
+ ksafety_black += EVAL_ADJACENTFILEOPEN;
+ }
+ break;
+ default:
+ break;
+ }
+ score_black += ksafety_black * board->material[WHITE] / 3100;
+ /********************************************************************
+ * return the values
+ ********************************************************************/
+ if (board->tomove == WHITE)
+ {
+ return (score_white + board->material[WHITE]) -
+ (score_black + board->material[BLACK]);
+ }
+ else
+ {
+ return (score_black + board->material[BLACK]) -
+ (score_white + board->material[WHITE]);
+ }
+}
+
+/**
+ * Special-case endgame evaluator
+ */
+static int16_t eval_endgame(board_t *board)
+{
+ int piece, square;
+ bitboard_t piecepos;
+ /* keeps track of {WHITE,BLACK}s score */
+ int16_t score_white = 0, score_black = 0;
+ int16_t difference = board->material[WHITE] -
+ board->material[BLACK];
+
+ /* draw evaluation - if no pawns are left, many possibilities
+ * note, our goal in this if block is to put the conditionals most
+ * likely to fail first, so we don't waste time saying "is the pawn's
+ * promotion square the opposite color of the bishop" when there's a
+ * queen on the board. */
+ if (!(board->pos[WHITE][PAWN] | board->pos[BLACK][PAWN]))
+ {
+ /* absolute value */
+ if (difference < 0) { difference = -difference; }
+
+ /* a good heuristic to use is if the material difference is
+ * less than 400, the position is drawn */
+ if (difference < 400)
+ {
+ return 0;
+ }
+
+ /* KNN vs K */
+ else if (difference == 600)
+ {
+ /* check if white has the two knights */
+ if ((board->material[BLACK] == 0) &&
+ (board->piecesofcolor[WHITE] ==
+ (board->pos[WHITE][KING] |
+ board->pos[WHITE][KNIGHT])))
+ {
+ return 0;
+ }
+ /* or black has the two knights */
+ if ((board->material[WHITE] == 0) &&
+ (board->piecesofcolor[BLACK] ==
+ (board->pos[BLACK][KING] |
+ board->pos[BLACK][KNIGHT])))
+ {
+ return 0;
+ }
+ /* here it must be a different piece configuration */
+ }
+ }
+ /* KB + wrong color rook pawn vs K */
+ else if (difference == 400)
+ {
+ /* first make sure it's KB rookpawn v K */
+ if ((board->material[BLACK] == 0) &&
+ (board->pos[WHITE][BISHOP] != BB(0x0)) &&
+ (board->pos[WHITE][PAWN] & (COL_A | COL_H)))
+ {
+ square_t pawnsquare = BITSCAN(board->pos[WHITE][PAWN]);
+ square_t bishopsquare = BITSCAN(board->pos[WHITE][BISHOP]);
+ square_t promotionsquare = SQUARE(COL(pawnsquare),RANK_8);
+ /* check the square parities and also where's
+ * the enemy king */
+ if ((PARITY(bishopsquare) != PARITY(promotionsquare)) &&
+ (kingattacks[BITSCAN(board->pos[BLACK][KING])] &
+ BB_SQUARE(promotionsquare)))
+ {
+ return 0;
+ }
+ }
+ /* same thing for the other color */
+ else if ((board->material[WHITE] == 0) &&
+ (board->pos[BLACK][BISHOP] != BB(0x0)) &&
+ (board->pos[BLACK][PAWN] & (COL_A | COL_H)))
+ {
+ square_t pawnsquare = BITSCAN(board->pos[BLACK][PAWN]);
+ square_t bishopsquare = BITSCAN(board->pos[BLACK][BISHOP]);
+ square_t promotionsquare = SQUARE(COL(pawnsquare),RANK_1);
+ /* check the square parities and also where's
+ * the enemy king */
+ if ((PARITY(bishopsquare) != PARITY(promotionsquare)) &&
+ (kingattacks[BITSCAN(board->pos[WHITE][KING])] &
+ BB_SQUARE(promotionsquare)))
+ {
+ return 0;
+ }
+ }
+ }
+ /* KP vs K - here we code just two cases, to facilitate the searcher;
+ * once we hit the back rank the searcher will see the draw itself.
+ * the first position is with the Ks in opposition with the pawn
+ * in between (either side to move, it's a draw); the second is
+ * with the pawn behind the winning king, in opposition (zugzwang) */
+ else if (difference == 100)
+ {
+ /* white has the pawn */
+ if (board->material[BLACK] == 0)
+ {
+ square_t whiteking = BITSCAN(board->pos[WHITE][KING]);
+ square_t blackking = BITSCAN(board->pos[BLACK][KING]);
+ square_t whitepawn = BITSCAN(board->pos[WHITE][PAWN]);
+ unsigned char pawncol = COL(whitepawn);
+ /* test for rook pawn draws */
+ if (pawncol == COL_A || pawncol == COL_H)
+ {
+ /* if black king gets in front of the pawn,
+ * it's a draw no matter what */
+ if ((COL(blackking) == pawncol) &&
+ (blackking > whitepawn))
+ {
+ return 0;
+ }
+ /* if the white king is in front of his pawn,
+ * but trapped by the black king, it'll end in
+ * stalemate */
+ if (COL(whiteking) == pawncol)
+ {
+ if (pawncol == COL_A)
+ {
+ if (blackking - whiteking == 2)
+ {
+ return 0;
+ }
+ }
+ else /* pawncol == COL_H */
+ {
+ if (whiteking - blackking == 2)
+ {
+ return 0;
+ }
+ }
+ }
+ }
+ if ((blackking - whiteking == 16) &&
+ (ROW(blackking) != RANK_8))
+ {
+ if (whitepawn - whiteking == 8)
+ {
+ return 0;
+ }
+ else if ((whiteking - whitepawn == 8) &&
+ (board->tomove == WHITE))
+ {
+ return 0;
+ }
+ }
+ }
+ /* black has the pawn */
+ else if (board->material[WHITE] == 0)
+ {
+ square_t whiteking = BITSCAN(board->pos[WHITE][KING]);
+ square_t blackking = BITSCAN(board->pos[BLACK][KING]);
+ square_t blackpawn = BITSCAN(board->pos[BLACK][PAWN]);
+ unsigned char pawncol = COL(blackpawn);
+ /* test for rook pawn draws */
+ if (pawncol == COL_A || pawncol == COL_H)
+ {
+ /* if black king gets in front of the pawn,
+ * it's a draw no matter what */
+ if ((COL(whiteking) == pawncol) &&
+ (whiteking < blackpawn))
+ {
+ return 0;
+ }
+ /* if the white king is in front of his pawn,
+ * but trapped by the black king, it'll end in
+ * stalemate */
+ if (COL(blackking) == pawncol)
+ {
+ if (pawncol == COL_A)
+ {
+ if (whiteking - blackking == 2)
+ {
+ return 0;
+ }
+ }
+ else /* pawncol == COL_H */
+ {
+ if (blackking - whiteking== 2)
+ {
+ return 0;
+ }
+ }
+ }
+ }
+ if ((blackking - whiteking == 16) &&
+ (ROW(whiteking) != RANK_1))
+ {
+ if (blackking - blackpawn == 8)
+ {
+ return 0;
+ }
+ else if ((blackpawn - blackking == 8) &&
+ (board->tomove == BLACK))
+ {
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* calculate piece/square totals */
+ for (piece = 0; piece < 6; piece++)
+ {
+ piecepos = board->pos[WHITE][piece];
+ while (piecepos)
+ {
+ square = BITSCAN(piecepos);
+ piecepos ^= BB_SQUARE(square);
+ score_white += eval_piecevalue_endgame[piece] +
+ eval_squarevalue_endgame[WHITE][piece][square];
+ }
+ }
+ for (piece = 0; piece < 6; piece++)
+ {
+ piecepos = board->pos[BLACK][piece];
+ while (piecepos)
+ {
+ square = BITSCAN(piecepos);
+ piecepos ^= BB_SQUARE(square);
+ score_black += eval_piecevalue_endgame[piece] +
+ eval_squarevalue_endgame[BLACK][piece][square];
+ }
+ }
+
+ /* return the values - we revalued the pieces to make pawns more
+ * important so board->material is inaccurate here */
+ if (board->tomove == WHITE)
+ {
+ return score_white - score_black;
+ }
+ else
+ {
+ return score_black - score_white;
+ }
+}
+
+/**
+ * Lazy evaluator
+ */
+int16_t eval_lazy(board_t *board)
+{
+ return board->material[board->tomove] -
+ board->material[OTHERCOLOR(board->tomove)];
+}
+/****************************************************************************
+ * movelist.c - data structure for move sorting in move generation/iteration
+ * copyright (C) 2008 Ben Blum
+ * ****************************************************************************/
+
+extern int16_t eval_squarevalue[2][6][64];
+
+/* Material values, add/subtract to find indices for moves which change the
+ * material count */
+static uint8_t movelist_material[] = { 1, 3, 3, 5, 9, 12 };
+
+/* arg 1 is the attacked boards, arg 2 is the move */
+static unsigned long movelist_findindex(uint64_t[2], uint32_t);
+
+/**
+ * Add a move. Determines where to add it using findindex
+ */
+void movelist_add(movelist_t *ml, uint64_t attackedby[2], uint32_t m)
+{
+ movelist_addtohead(ml, m, movelist_findindex(attackedby, m));
+}
+
+/**
+ * Determine at which index in the movelist a move should be added
+ */
+static unsigned long movelist_findindex(uint64_t attackedby[2], uint32_t m)
+{
+ int16_t materialgain;
+ /* which side has the move? this is a substitute for board->tomove */
+ unsigned char tomove = MOV_COLOR(m);
+
+ if (MOV_PROM(m))
+ {
+ if (MOV_PROMPC(m) == QUEEN)
+ {
+ /* MOV_CAPT is 1 or 0 */
+ return MOVELIST_INDEX_PROM_QUEEN + MOV_CAPT(m);
+ }
+ return MOVELIST_INDEX_PROM_MINOR;
+ }
+ if (MOV_CASTLE(m))
+ {
+ /* The second term will be 1 if O-O, 0 if O-O-O */
+ return MOVELIST_INDEX_CASTLE + (COL(MOV_DEST(m)) == COL_G);
+ }
+ if (MOV_CAPT(m))
+ {
+ materialgain = movelist_material[MOV_CAPTPC(m)];
+ /* see if the capturing piece will be recaptured - assume it
+ * will be if the opponent attacks that square at all */
+ if (attackedby[OTHERCOLOR(tomove)] & BB_SQUARE(MOV_DEST(m)))
+ {
+ /* this will index past the end of the array if the
+ * moving piece is a king - we rely on the board
+ * library to filter out suicide king captures */
+ materialgain -= movelist_material[MOV_PIECE(m)];
+ /* neutral capture */
+ if (materialgain == 0)
+ {
+ return MOVELIST_INDEX_NEUTRAL + MOV_PIECE(m);
+ }
+ //real SEE could be done here
+ }
+ /* losing material */
+ else if (materialgain < 0)
+ {
+ return MOVELIST_INDEX_MAT_LOSS + materialgain;
+ }
+ /* winning capture */
+ else
+ {
+ return MOVELIST_INDEX_MAT_GAIN + materialgain;
+ }
+ }
+ /* here it's a regular move */
+ /* moving the piece where it can be captured */
+ if (attackedby[OTHERCOLOR(tomove)] & BB_SQUARE(MOV_DEST(m)))
+ {
+ /* Moves that put the king in check are only generated if the
+ * attackedby bitmasks don't see it, so we won't fall apart on
+ * one either - they just get poor ordering, which is fine. */
+ assert(MOV_PIECE(m) != KING);
+ /* if we can recapture after being captured */
+ if (attackedby[tomove] & BB_SQUARE(MOV_DEST(m)))
+ {
+ /* if the moving piece is better than a pawn, call it
+ * a loss. otherwise, assume the pawn won't be taken
+ * (and fall through to the next phase). */
+ if (MOV_PIECE(m) != PAWN)
+ {
+ /* give an "approximate" SEE - guessing, when
+ * we recapture we'll get between 1 and 3 */
+ return MOVELIST_INDEX_MAT_LOSS + 2 -
+ movelist_material[MOV_PIECE(m)];
+ }
+ //real SEE could be done here
+ }
+ /* if we move to a hanging square, we consider it complete
+ * loss of that piece */
+ else
+ {
+ return MOVELIST_INDEX_MAT_LOSS -
+ movelist_material[MOV_PIECE(m)];
+ }
+ }
+ /* here our piece is safe on its destination - let's see if we were
+ * saving it from being captured otherwise ("unhang"ing the piece); if
+ * so, it goes in the material gain category */
+ if ((attackedby[OTHERCOLOR(tomove)] & ~(attackedby[tomove])) &
+ BB_SQUARE(MOV_SRC(m)))
+ {
+ return MOVELIST_INDEX_MAT_GAIN +
+ movelist_material[MOV_PIECE(m)];
+ }
+ /* regular move */
+ return MOVELIST_INDEX_REGULAR +
+ eval_squarevalue[tomove][MOV_PIECE(m)][MOV_DEST(m)] -
+ eval_squarevalue[tomove][MOV_PIECE(m)][MOV_SRC(m)];
+}
+
+void movelist_addtohead(movelist_t *mlp, uint32_t m, unsigned long index)
+{
+ movelist_inner_t *ml = *mlp;
+ /* sanity check */
+ assert(index < MOVELIST_NUM_BUCKETS);
+ /* add to list */
+ assert(ml->sublist_count[index] < MOVELIST_SUBLIST_LENGTH);
+ ml->array[index][ml->sublist_count[index]] = m;
+ ml->sublist_count[index]++;
+
+ /* adjust max pointer */
+ if (index > ml->max)
+ {
+ ml->max = index;
+ }
+ return;
+}
+
+int movelist_isempty(movelist_t *mlp)
+{
+ movelist_inner_t *ml = *mlp;
+ return (ml->sublist_count[ml->max] == 0);
+}
+
+/* Don't call this if movelist_isempty! */
+uint32_t movelist_remove_max(movelist_t *mlp)
+{
+ movelist_inner_t *ml = *mlp;
+ uint32_t returnval = ml->array[ml->max][--ml->sublist_count[ml->max]];
+ /* check if we need to adjust the max pointer */
+ while (movelist_isempty(mlp))
+ {
+ /* we hit the bottom of the array; doesn't matter if empty */
+ if (ml->max == 0)
+ {
+ break;
+ }
+ ml->max--;
+ }
+ return returnval;
+}
+/****************************************************************************
+ * pawnstructure.c - evaluation helpers to judge pawn structure quality
+ * copyright (C) 2008 Ben Blum
+ * ****************************************************************************/
+
+/* We do pawn square scoring here rather than in eval.c to save time */
+extern int16_t eval_squarevalue[2][6][64];
+
+typedef struct ps_entry_t {
+ bitboard_t key;
+ bitboard_t holes;
+ int16_t value;
+} ps_entry_t;
+
+/* this is a lot like the transposition table in case you haven't noticed... */
+#ifndef PS_NUM_BUCKETS
+#define PS_NUM_BUCKETS (32 * 1024 * 1024 / sizeof(ps_entry_t)) // 32MB
+#endif
+static ps_entry_t ps_array[PS_NUM_BUCKETS];
+
+static void ps_add(bitboard_t key, bitboard_t holes, int16_t value)
+{
+ unsigned long bucket;
+
+ /* find the bucket */
+ bucket = key % PS_NUM_BUCKETS;
+ /* always evict */
+ ps_array[bucket].key = key;
+ ps_array[bucket].holes = holes;
+ ps_array[bucket].value = value;
+
+ return;
+}
+
+/**
+ * Fetch data from the table.
+ */
+#define PAWNSTRUCTURE_LOOKUP_FAIL INT16_MIN
+static int16_t ps_get(bitboard_t key, bitboard_t *holes)
+{
+ unsigned long bucket = key % PS_NUM_BUCKETS;
+ if (ps_array[bucket].key == key)
+ {
+ *holes = ps_array[bucket].holes;
+ return ps_array[bucket].value;
+ }
+ return PAWNSTRUCTURE_LOOKUP_FAIL;
+}
+
+/* Bonus for pawn chains - for each pawn protected by another, add bonus */
+#ifndef PS_CHAIN_BONUS
+#define PS_CHAIN_BONUS 2
+#endif
+/* Penalty for doubling pawns - for each pawn with another pawn on its file,
+ * subtract the penalty (note, tripled pawns net loss 6 times this!) */
+#ifndef PS_DOUBLED_PENALTY
+#define PS_DOUBLED_PENALTY 8
+#endif
+/* Isolated penalty - for each pawn with no brothers on adjacent files
+ * note, if a pawn gets this penalty it will also get the backwards penalty */
+#ifndef PS_ISOLATED_PENALTY
+#define PS_ISOLATED_PENALTY 16
+#endif
+/* Backward pawns - nothing on same rank or behind on adjacent columns */
+#ifndef PS_BACKWARD_PENALTY
+#define PS_BACKWARD_PENALTY 8
+#endif
+
+/* Bonuses for having a passed pawn of <color> on the given <rank> */
+int16_t pawnstructure_passed_bonus[2][8] = {
+ { 0, 3, 6, 12, 24, 48, 96, 0 },
+ { 0, 96, 48, 24, 12, 6, 3, 0 }
+};
+
+/**
+ * Pawnstructure evaluator - color being whose pawns these are, and holes a
+ * pass-by-reference second return value - a chart of all "holes" in the pawn
+ * structure; that is, all squares which can never be attacked by these pawns.
+ */
+int16_t eval_pawnstructure(board_t *board, unsigned char color, bitboard_t *h)
+{
+ /* the value we calculate and store in the hashtable */
+ int16_t value;
+ /* value dependent on factors outside of just the pawn pos, so we
+ * cannot hash this and must calculate even if the cache hits */
+ int16_t unhashable_bonus = 0;
+
+ square_t square;
+ bitboard_t pawns, pos, friends, everybodyelse, behindmask, holes;
+
+ pawns = board->pos[color][PAWN];
+
+ /* attempt to lookup - if we succeed, only need to calculate the
+ * unhashable bonus. pass in the h ptr as well; if the lookup
+ * fails it'll be untouched */
+ if ((value = ps_get(pawns, h)) != PAWNSTRUCTURE_LOOKUP_FAIL)
+ {
+ while (pawns)
+ {
+ square = BITSCAN(pawns);
+ pawns ^= BB_SQUARE(square);
+ if (board_pawnpassed(board, square, color))
+ {
+ unhashable_bonus += pawnstructure_passed_bonus[color][ROW(square)];
+ }
+ }
+ return value + unhashable_bonus;
+ }
+
+ /* holes starts with everything set, and we take off bits that our
+ * pawns could attack (using passedpawn masks for this) */
+ holes = ~BB_SQUARE(0x0);
+ /* for each pawn, consider its value with relation to the structure */
+ pos = pawns;
+ while (pos)
+ {
+ /* find and clear a bit */
+ square = BITSCAN(pos);
+ pos ^= BB_SQUARE(square);
+ /* piece/square table */
+ value += eval_squarevalue[color][PAWN][square];
+
+ /* check for passed pawn */
+ if (board_pawnpassed(board, square, color))
+ {
+ unhashable_bonus += pawnstructure_passed_bonus[color][ROW(square)];
+ }
+
+ everybodyelse = pawns ^ BB_SQUARE(square);
+
+ /* first evaluate chaining */
+ friends = everybodyelse & pawnattacks[color][square];
+ value += PS_CHAIN_BONUS * POPCOUNT(friends);
+
+ /* next, doubled pawns */
+ friends = everybodyelse & BB_FILE(COL(square));
+ value -= PS_DOUBLED_PENALTY * POPCOUNT(friends);
+
+ /* backwards */
+ friends = everybodyelse & bb_adjacentcols[COL(square)];
+ /* get a mask of all squares behind/same rank as this square */
+ if (color == WHITE)
+ {
+ behindmask = (BB_SQUARE(square) ^ (BB_SQUARE(square) - 1)) |
+ BB_RANK(ROW(square));
+ }
+ else
+ {
+ behindmask = (BB_SQUARE(square) ^ (-BB_SQUARE(square))) |
+ BB_RANK(ROW(square));
+ }
+ if (!(friends & behindmask))
+ {
+ value -= PS_BACKWARD_PENALTY;
+ /* see if isolated entirely */
+ if (!friends) /* SO RONERY */
+ {
+ value -= PS_ISOLATED_PENALTY;
+ }
+ }
+ /* calculate holes in pawnstructure - any squares that this
+ * pawn may be able to attack, take out of the bitmap */
+ holes ^= (bb_passedpawnmask[color][square] & ~BB_FILE(COL(square)));
+ }
+ ps_add(pawns, holes, value);
+ *h = holes;
+ return value + unhashable_bonus;
+}
+/****************************************************************************
+ * popcnt.c - various population-count implementations
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+/**
+ * Kernighan's LSB-resetting popcount implementation
+ */
+int popcnt(uint64_t x)
+{
+ int count = 0;
+ while (x)
+ {
+ count++;
+ x &= x - 1; // reset LS1B
+ }
+ return count;
+}
+
+/**
+ * Good on procs with slow multiplication
+ */
+int popcnt2(uint64_t x)
+{
+ x -= (x >> 1) & 0x5555555555555555ull;
+ x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull);
+ x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0full;
+ x += x >> 8;
+ x += x >> 16;
+ x += x >> 32;
+ return x & 0x7f;
+}
+
+/**
+ * Good on procs with fast multiplication
+ */
+int popcnt3(uint64_t x) {
+ x -= (x >> 1) & 0x5555555555555555ull;
+ x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull);
+ x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0full;
+ return (x * 0x0101010101010101ull)>>56;
+}
+/****************************************************************************
+ * quiescent.c - captures-only search to avoid evaluating unstable positions
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+extern volatile unsigned char timeup;
+extern int lazy, nonlazy;
+
+#ifndef QUIESCENT_MAX_DEPTH
+/* Warning: NEVER put this at 4 or below - it causes the bot to be too weak */
+#define QUIESCENT_MAX_DEPTH 8
+#endif
+
+static int16_t qalphabeta(board_t *, int16_t, int16_t, uint8_t);
+
+/**
+ * Play out capture chains in a position until it's quiet (or until a certain
+ * depth is reached, for speed) so we can accurately use the evaluator
+ */
+int16_t quiesce(board_t *board, int16_t alpha, int16_t beta)
+{
+ return qalphabeta(board, alpha, beta, QUIESCENT_MAX_DEPTH);
+}
+
+/**
+ * Alpha beta searching over captures. Don't need to return a move, only the
+ * value. No repetition/50-move checking (obvious reasons), no transposition
+ * table (simplicity) - we get pretty good move ordering for captures already
+ * from the board library.
+ */
+static int16_t qalphabeta(board_t *board, int16_t alpha, int16_t beta,
+ uint8_t depth)
+{
+ movelist_t moves;
+ move_t curmove;
+ /* who has the move */
+ int color;
+ //XXX: due to we're only generating captures, we can't check if we get
+ //XXX: mated here... this seems bad, but should turn out ok (i.e., a
+ //XXX: quiescence that doesn't see mates is better than no quiescence
+ //XXX: at all.
+
+ /* used in place of lastval */
+ int16_t a;
+
+ /* what happens if the player to move declines to make any captures */
+ int16_t stand_pat;
+
+ if (timeup)
+ {
+ return 0;
+ }
+
+ /* we'll be using stand_pat in a lot of places*/
+ /* first do a lazy evaluation; if it's too far from the window we will
+ * not need the precision of eval() */
+ stand_pat = eval_lazy(board);
+ /* check if we're not allowed to be lazy */
+ if ((stand_pat > (alpha - EVAL_LAZY_THRESHHOLD)) &&
+ (stand_pat < (beta + EVAL_LAZY_THRESHHOLD)))
+ {
+ stand_pat = eval(board);
+ nonlazy++;
+ }
+ else { lazy++; }
+
+ /********************************************************************
+ * terminal condition - search depth ran out
+ ********************************************************************/
+ if (depth == 0)
+ {
+ return stand_pat;
+ }
+
+ /********************************************************************
+ * Main iteration over all the moves
+ ********************************************************************/
+ /* set some preliminary values */
+ if (stand_pat > alpha)
+ {
+ if (stand_pat >= beta)
+ {
+ return stand_pat;
+ }
+ alpha = stand_pat;
+ }
+ color = board->tomove;
+
+ /* and we're ready to go */
+ board_generatecaptures(board, &moves);
+ while (!movelist_isempty(&moves))
+ {
+ if (timeup)
+ {
+ break;
+ }
+ curmove = movelist_remove_max(&moves);
+
+ board_applymove(board, curmove);
+ /* see if this move puts us in check */
+ if (board_colorincheck(board, color))
+ {
+ board_undomove(board, curmove);
+ continue;
+ }
+ a = -qalphabeta(board, -beta, -alpha, depth-1);
+ board_undomove(board, curmove);
+
+ if (a > alpha)
+ {
+ alpha = a;
+ }
+ if (beta <= alpha)
+ {
+ break;
+ }
+ }
+ movelist_destroy(&moves);
+
+ return alpha; /* will work even if no captures were available */
+}
+/****************************************************************************
+ * rand.c - wrappers for GSL random number generation utilities
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+uint32_t
+rand32(void)
+{
+ rand_init();
+ return genrand();
+}
+
+static unsigned char rand_initted = 0;
+
+void rand_init()
+{
+ if (rand_initted)
+ {
+ return;
+ }
+ sgenrand(get_ticks());
+ rand_initted = 1;
+}
+
+uint64_t rand64()
+{
+ return ((uint64_t)rand32()) | (((uint64_t)rand32()) << 32);
+}
+
+/****************************************************************************
+ * search.c - traverse the game tree looking for the best position
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+/* Constants for the search algorithm */
+#define SEARCHER_INFINITY 32767
+#define SEARCHER_MATE 16383
+
+/* could be changed if you wanted to {dis,en}courage draws
+ * TODO: make the evaluator also use this */
+#define SEARCHER_DRAW_SCORE 0
+#define VALUE_ISDRAW(v) ((v) == SEARCHER_DRAW_SCORE)
+
+static move_t alphabeta(board_t *, int16_t, int16_t, uint8_t, uint8_t, move_t, uint8_t, uint8_t, unsigned char);
+
+int transposition_hits, transposition_misses;
+extern int regen_hits, regen_misses;
+
+static int nodes;
+static int16_t lastval;
+
+/* used for printing stuff */
+extern int outbuf_size;
+extern int text_loud;
+extern char outbuf[];
+void output();
+
+/* Used for iterative deepening and replacement policy in the trans table */
+static uint8_t cur_searching_depth;
+
+/* used for iterative deepening */
+volatile unsigned char timeup;
+
+#define SEARCHER_MIN_DEPTH 2
+#define SEARCHER_MAX_DEPTH 64
+// configurable; must never get bigger than MAX_DEPTH-1
+unsigned int searcher_max_depth = SEARCHER_MAX_DEPTH-1;
+
+#define VALUE_ISMATE(v) (((v) >= SEARCHER_MATE - SEARCHER_MAX_DEPTH) || ((v) <= -(SEARCHER_MATE - SEARCHER_MAX_DEPTH)))
+
+/* aspiration windows - first try a window of aspir_1 around prevalpha; if
+ * that fails go to aspir_2; if that fails use the full -inf,+inf search */
+#define SEARCHER_ASPIRATION_1 50
+#define SEARCHER_ASPIRATION_2 200
+
+/* killer moves
+ *
+ * Tried at each move after the hashed bestmove, before generatemoves(). A
+ * killer move is basically any move by one player that produces a beta cutoff
+ * when the pther player makes a move from X position; the hope here is that
+ * the same refutation move will produce a cutoff in the next children of X.
+ * This is likely to happen if the first player is threatened somehow, and the
+ * killer will be the followthrough on that threat if player one doesn't
+ * respond to it.
+ *
+ * note - you will want to clear all the killers in the following cases:
+ * 1) Beginning/end of getbestmove - clear all depths
+ * 2) After a node finishes its children, clear the nodes at that
+ * child's ply
+ * If the killers are not adequately cleared, you may end up applying some
+ * illegal moves at other nodes, resulting in inconsistent board state.
+ * Another thing to watch out for is some killers can still be illegal - most
+ * cases are eliminated by preventing captures and castles, the rest need
+ * checking against board_attacksfrom() (or pushes, in the case of pawns).
+ */
+#define SEARCHER_USE_KILLERS
+#ifdef SEARCHER_USE_KILLERS
+#define SEARCHER_NUM_KILLERS 3
+static move_t killers[SEARCHER_MAX_DEPTH][SEARCHER_NUM_KILLERS];
+#endif
+
+/* margins for futility pruning - how far away from the window do we need
+ * to be in order to consider doing futility pruning. note that the value at
+ * 0 will never be used */
+#ifdef SEARCHER_FUTILITY_PRUNING
+static int16_t futility_margin[3] = { 0xbeef, 250, 450 };
+#endif
+
+int lazy, nonlazy;
+
+/* determining the type of a child from a parent (first index - parent's type)
+ * given whether the first child (0 or 1, second index) has been searched */
+#define PV 0
+#define CUT 1
+#define ALL 2
+static unsigned char childnodetype[3][2] = {
+ /* first child already searched:
+ * NO YES */
+ { PV, CUT }, /* parent was PV */
+ { ALL, CUT }, /* parent was CUT */
+ { CUT, CUT } /* parent was ALL */
+};
+
+/* null-move depth reduction - dependent on depth */
+#define NULLMOVE_R(d) (((d) > 6) ? 3 : 2)
+
+/* Late move reduction - we reduce after searching this many nodes given the
+ * current node type (allows us to be more conservative at PV nodes) */
+static uint8_t lmr_movecount[3] = { 16, 8, 8 };
+
+#define GUESS_KERNEL_HZ 100 // I really wish the syscall interface exposed this.
+
+void *sigalrm_thread(void *arg)
+{
+ sleep((int)arg * GUESS_KERNEL_HZ);
+ timeup = 1;
+ return (void *)0x15410FA1L;
+}
+
+/**
+ * Stores the nodecount in the given int pointer if it's nonnull and the alpha
+ * value in the second pointer if that's nonnull.
+ */
+move_t getbestmove(board_t *board, unsigned int time, int *nodecnt, int16_t *alphaval)
+{
+ move_t result, prevresult;
+ int16_t prevalpha;
+ int16_t window_low, window_high;
+ char *movestr;
+ int ret;
+ void *statusp;
+
+ /********************************************************************
+ * Setup
+ ********************************************************************/
+ nodes = 0;
+ timeup = 0;
+
+ transposition_hits = 0; transposition_misses = 0;
+ regen_hits = 0; regen_misses = 0;
+
+ lazy = 0; nonlazy = 0;
+
+ #ifdef SEARCHER_USE_KILLERS
+ /* clear all killers */
+ memset(killers, 0, sizeof(killers));
+ #endif
+ /********************************************************************
+ * Searching
+ ********************************************************************/
+ snprintf(outbuf, outbuf_size, "Thinking (for %d %s)...",
+ time, time == 1 ? "sec" : "secs");
+ output();
+ /* preliminary search */
+ cur_searching_depth = SEARCHER_MIN_DEPTH;
+ result = alphabeta(board, -SEARCHER_INFINITY, SEARCHER_INFINITY,
+ cur_searching_depth, 0, 0, 0, 0, PV);
+ prevresult = result;
+ prevalpha = lastval;
+
+ /* start the iterative timer */
+ ret = thr_create(sigalrm_thread, (void *)time);
+ assert(ret > 0 && "Failed to create timer thread");
+
+ while (!timeup && cur_searching_depth < searcher_max_depth)
+ {
+ /* These guys store the result of the previous depth in case
+ * our next search times up */
+ prevresult = result;
+ prevalpha = lastval;
+
+ // Don't waste time if we have a mate
+ /*if (lastval >= SEARCHER_MATE)
+ {
+ break;
+ }*/
+
+ //TODO: Check if we've used up enough time to not even bother with the next search
+
+ /* advance to the next depth */
+ movestr = move_tostring(result);
+ if (text_loud) {
+ snprintf(outbuf, outbuf_size, "[depth %d] best %s score %d",
+ cur_searching_depth, movestr, lastval);
+ output();
+ }
+ if (VALUE_ISMATE(lastval) && text_loud)
+ {
+ snprintf(outbuf, outbuf_size, "%s mates in %d",
+ ((lastval > 0) ?
+ ((board->tomove == WHITE) ? "White" : "Black")
+ :
+ ((board->tomove == WHITE) ? "Black" : "White")),
+ ((lastval > 0) ?
+ ((SEARCHER_MATE - lastval + 1) / 2)
+ :
+ ((SEARCHER_MATE + lastval + 1) / 2)));
+ output();
+ }
+ free(movestr);
+ cur_searching_depth++;
+ nodes = 0;
+
+ window_low = prevalpha - SEARCHER_ASPIRATION_1;
+ window_high = prevalpha + SEARCHER_ASPIRATION_1;
+ result = alphabeta(board, window_low, window_high,
+ cur_searching_depth, 0, 0, 0, 0, PV);
+ if (timeup) break;
+ /* test if aspir_1 window failed */
+ if (lastval <= window_low || lastval >= window_high)
+ {
+ /* try wider window */
+ window_low = prevalpha - SEARCHER_ASPIRATION_2;
+ window_high = prevalpha + SEARCHER_ASPIRATION_2;
+ /* re-search */
+ result = alphabeta(board, window_low, window_high,
+ cur_searching_depth, 0, 0, 0, 0, PV);
+ }
+ if (timeup) break;
+ /* test if aspir_2 window failed */
+ if (lastval <= window_low || lastval >= window_high)
+ {
+ /* use full window */
+ window_low = -SEARCHER_INFINITY;
+ window_high = SEARCHER_INFINITY;
+ /* re-search */
+ result = alphabeta(board, window_low, window_high,
+ cur_searching_depth, 0, 0, 0, 0, PV);
+ }
+ }
+
+ /********************************************************************
+ * Teardown
+ ********************************************************************/
+ movestr = move_tostring(prevresult);
+ if (text_loud) {
+ if (timeup) {
+ snprintf(outbuf, outbuf_size, "[depth %d] (timeout, %d nodes)",
+ cur_searching_depth, nodes);
+ } else {
+ snprintf(outbuf, outbuf_size, "[depth %d] best %s score %d",
+ cur_searching_depth, movestr, lastval);
+ }
+ output();
+ }
+ snprintf(outbuf, outbuf_size, "My move: %s", movestr);
+ output();
+ free(movestr);
+ #ifdef SEARCHER_USE_KILLERS
+ /* clear killers, just in case */
+ memset(killers, 0, sizeof(killers));
+ #endif
+ if (nodecnt != NULL)
+ {
+ *nodecnt = nodes;
+ }
+ if (alphaval != NULL)
+ {
+ *alphaval = prevalpha;
+ }
+ // TODO: Do this in a non-blocking way all the time.
+ thr_join(ret, &statusp);
+ assert(statusp == (void*)0x15410FA1L);
+ return prevresult;
+}
+
+/**
+ * Alpha-beta search, with trans table, check extension, futility pruning
+ * board - the current node's position
+ * alpha - lower bound
+ * beta - upper bound
+ * depth - how deep we will search this node
+ * ply - how far this position is from the board's real position (used
+ * because depth can change based on extensions/reductions)
+ * prevmove - the move that was just made (used in futility pruning)
+ * num_checks - how many checks have occurred so far in the search (used for
+ * check extension)
+ * nodetype - what type of node we're searching - PV, CUT, or ALL
+ */
+static move_t alphabeta(board_t *board, int16_t alpha, int16_t beta,
+ uint8_t depth, uint8_t ply, move_t prevmove,
+ uint8_t num_checks, uint8_t null_extended,
+ unsigned char nodetype)
+{
+ movelist_t moves;
+ move_t curmove, returnmove;
+ /* who has the move */
+ int color;
+ /* used for telling if the movelist we got had no non-suicide moves,
+ * also for telling what the child's node type will be */
+ unsigned char children_searched;
+
+ /* transposition table */
+ trans_data_t trans_data;
+ int trans_flag;
+ /* for move ordering */
+ move_t bestmove;
+
+ int killer_index;
+
+ nodes++;
+ if (timeup)
+ {
+ return 0;
+ }
+ /********************************************************************
+ * threefold repetition/50 move - always check first
+ ********************************************************************/
+ /* draw score if only even -one- prior repetition, not two. this is
+ * more efficient (taken from crafty). note that it obsoletes storing
+ * the repetition count in the trans table, but if it gets put back,
+ * transing the reps will still be essential. */
+ if (board->halfmoves >= 100 || board_threefold_draw(board))
+ {
+ //fprintf(ttyout, "%sSEARCHER: Detected threefold repetition at depth %d%s\n",
+ // TTYOUT_COLOR, cur_searching_depth - depth, DEFAULT_COLOR);
+ lastval = SEARCHER_DRAW_SCORE;
+ return 0;
+ }
+ /********************************************************************
+ * check transposition table
+ ********************************************************************/
+ trans_data = trans_get(board->hash);
+ if (trans_data_valid(trans_data))
+ {
+ if (TRANS_SEARCHDEPTH(trans_data) >= depth &&
+ TRANS_REPS(trans_data) >= board->reps)
+ {
+ int16_t storedval = TRANS_VALUE(trans_data);
+
+ /* direct hit! */
+ if (TRANS_FLAG(trans_data) == TRANS_FLAG_EXACT)
+ {
+ transposition_hits++;
+ lastval = storedval;
+ return TRANS_MOVE(trans_data);
+ }
+ /* if we do this on the root node, we run the risk of
+ * getting a1a1 as the returnmove, so prevent it */
+ else if (depth != cur_searching_depth)
+ {
+ /* we have a lower bound for the true value */
+ if (TRANS_FLAG(trans_data) == TRANS_FLAG_BETA)
+ {
+ /* above our current window? */
+ if (storedval >= beta)
+ {
+ transposition_hits++;
+ lastval = storedval;
+ return 0;
+ }
+ /* not above the window but inside? */
+ if (storedval > alpha)
+ {
+ alpha = storedval;
+ }
+ }
+ /* this means we'll have an upper bound */
+ else if (TRANS_FLAG(trans_data) ==
+ TRANS_FLAG_ALPHA)
+ {
+ /* below current window entirely? */
+ if (storedval <= alpha)
+ {
+ transposition_hits++;
+ lastval = storedval;
+ return 0;
+ }
+ /* inside window - cut the top off */
+ if (storedval < beta)
+ {
+ beta = storedval;
+ }
+ }
+ }
+ }
+ /* well, we can still use move-ordering information. note:
+ * we'll want to grab it regardless of the flag. if it's beta
+ * we'll get a move; if it's alpha we'll get 0; oh well */
+ bestmove = TRANS_MOVE(trans_data);
+ }
+ else
+ {
+ bestmove = (move_t)0;
+ transposition_misses++;
+ }
+ /********************************************************************
+ * terminal condition - search depth ran out
+ * futility pruning done here
+ ********************************************************************/
+ if (depth == 0)
+ {
+ lastval = quiesce(board, alpha, beta);
+ /* we time up in the middle of quiescence and get zero, and go
+ * to add it in the trans table, OH SHI-- */
+ if (timeup)
+ {
+ return 0;
+ }
+ /* if we already have an entry, and this is an end condition,
+ * we don't want to replace our better entry */
+ if (!trans_data_valid(trans_data))
+ {
+ trans_add(board->hash, (move_t)0, board->reps, lastval,
+ (board->moves - cur_searching_depth),
+ board->moves, 0, TRANS_FLAG_EXACT);
+ }
+ return 0;
+ }
+ #ifdef SEARCHER_FUTILITY_PRUNING
+ /* futility pruning - prune only 1 and 2 plies from the horizon */
+ else if (depth < 3)
+ {
+ /* if we're in check or possibly in a capture sequence, trying
+ * to prune will be too dangerous */
+ if (!(board_incheck(board) || MOV_CAPT(prevmove)))
+ {
+ int16_t score = eval_lazy(board);
+ /* check how far we are from the window */
+ if ((score + futility_margin[depth] < alpha) ||
+ (score - futility_margin[depth] > beta))
+ {
+ lastval = quiesce(board, alpha, beta);
+ return 0;
+ }
+ }
+ }
+ #endif
+ /********************************************************************
+ * Null-move pruning
+ ********************************************************************/
+ /* only do it if all of the following:
+ * we're a fail-high (CUT) node
+ * depth is not three or less
+ * we're not in the endgame
+ * a lazy eval fails high
+ * we're not in check
+ */
+ if ((nodetype != PV) && (depth > 3) && !eval_isendgame(board) &&
+ (eval_lazy(board) >= beta) && !board_incheck(board))
+ {
+ /* make null move */
+ board_applymove(board, 0);
+ alphabeta(board, -beta, -beta+1, depth - NULLMOVE_R(depth) - 1,
+ ply+1, 0, num_checks, null_extended, ALL);
+ board_undomove(board, 0);
+
+ /* failed high, we can prune */
+ if (-lastval >= beta)
+ {
+ lastval = -lastval;
+ return 0;
+ }
+ /* mate threat - if we do nothing here, we get mated. better
+ * search deeper. only extend this way once per line. */
+ if (VALUE_ISMATE(lastval) && !null_extended)
+ {
+ depth++;
+ null_extended = 1;
+ }
+ }
+ /********************************************************************
+ * Main iteration over all the moves
+ ********************************************************************/
+ /* set some preliminary values */
+ color = board->tomove;
+ children_searched = 0;
+ returnmove = 0;
+ trans_flag = TRANS_FLAG_ALPHA;
+ /* and we're ready to go - first do hash move and killers */
+ if (bestmove)
+ {
+ board_applymove(board, bestmove);
+ /* if this puts us in check something's really wrong... */
+ assert(!board_colorincheck(board, color));
+ /* check extension - if this checks the opp king */
+ if (board_incheck(board))
+ {
+ /* only extend search if >1 checks in tree */
+ if (num_checks)
+ {
+ alphabeta(board, -beta, -alpha, depth, ply+1,
+ bestmove, num_checks+1, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ else
+ {
+ alphabeta(board, -beta, -alpha, depth-1, ply+1,
+ bestmove, num_checks+1, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ }
+ else /* no extensions, regular search */
+ {
+ alphabeta(board, -beta, -alpha, depth-1, ply+1,
+ bestmove, num_checks, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ board_undomove(board, bestmove);
+ children_searched++;
+
+ if (-lastval > alpha)
+ {
+ alpha = -lastval;
+ returnmove = bestmove;
+ trans_flag = TRANS_FLAG_EXACT;
+ }
+ if (alpha >= beta)
+ {
+ trans_flag = TRANS_FLAG_BETA;
+ goto alphabeta_after_iteration;
+ }
+ }
+ #ifdef SEARCHER_USE_KILLERS
+ /* no cutoff from the bestmove (or no bestmove); let's try killers */
+ for (killer_index = 0; killer_index < SEARCHER_NUM_KILLERS; killer_index++)
+ {
+ move_t killer = killers[ply][killer_index];
+ piece_t killerpiece;
+ square_t killersrc, killerdest;
+ /* check if a killer is available */
+ if (killer == 0 || timeup)
+ {
+ break;
+ }
+ killerpiece = MOV_PIECE(killer);
+ killersrc = MOV_SRC(killer);
+ killerdest = MOV_DEST(killer);
+ /* need to check if the killer is legal in this position; it's
+ * guaranteed to not be a capture or castle, so the following
+ * legality checks are made:
+ * 1) We have the given piece on that square
+ * 2) The destination square is not occupied (by either color)
+ * 3) If a sliding piece, there must be nothing in the way */
+ if ((!(BB_SQUARE(killersrc) & board->pos[color][killerpiece])) ||
+ (BB_SQUARE(killerdest) & board->occupied) || /* #2 */
+ (PIECE_SLIDES(killerpiece) && /* #3 */
+ !(BB_SQUARE(killerdest) &
+ board_attacksfrom(board, killersrc, killerpiece, color))))
+ {
+ continue;
+ }
+ /* next we check if our piece can move to the destsquare */
+ if (killerpiece == PAWN)
+ {
+ /* destination square not among the legal pushes? */
+ if (!(BB_SQUARE(killerdest) &
+ board_pawnpushesfrom(board, killersrc, color)))
+ {
+ continue;
+ }
+ }
+ else
+ {
+ /* destination square not among the legal moves? */
+ if (!(BB_SQUARE(killerdest) &
+ board_attacksfrom(board, killersrc, killerpiece,
+ color)))
+ {
+ continue;
+ }
+ }
+ /* we have a pseudolegal killer move to try, good */
+ board_applymove(board, killer);
+ /* this might put us in check, unlike the bestmove */
+ if (board_colorincheck(board, color))
+ {
+ board_undomove(board, killer);
+ continue;
+ }
+ /* check extension - if this checks the opp king */
+ if (board_incheck(board))
+ {
+ /* only extend search if >1 checks in tree */
+ if (num_checks)
+ {
+ alphabeta(board, -beta, -alpha, depth, ply+1,
+ killer, num_checks+1, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ else
+ {
+ alphabeta(board, -beta, -alpha, depth-1, ply+1,
+ killer, num_checks+1, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ }
+ else /* no extensions, regular search */
+ {
+ alphabeta(board, -beta, -alpha, depth-1, ply+1,
+ killer, num_checks, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ board_undomove(board, killer);
+ children_searched++;
+
+ if (-lastval > alpha)
+ {
+ alpha = -lastval;
+ returnmove = killer;
+ trans_flag = TRANS_FLAG_EXACT;
+ }
+ if (alpha >= beta)
+ {
+ trans_flag = TRANS_FLAG_BETA;
+ goto alphabeta_after_iteration;
+ }
+ }
+ #endif
+ /* okay, no beta cutoff; let's continue... */
+ board_generatemoves(board, &moves);
+ while (!movelist_isempty(&moves))
+ {
+ if (timeup)
+ {
+ break;
+ }
+ curmove = movelist_remove_max(&moves);
+
+ board_applymove(board, curmove);
+ /* see if this move puts us in check */
+ if (board_colorincheck(board, color))
+ {
+ board_undomove(board, curmove);
+ continue;
+ }
+ /* check extension - if this checks the opp king */
+ if (board_incheck(board))
+ {
+ /* only extend search if >1 checks in tree */
+ if (num_checks)
+ {
+ alphabeta(board, -beta, -alpha, depth, ply+1,
+ curmove, num_checks+1, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ else
+ {
+ alphabeta(board, -beta, -alpha, depth-1, ply+1,
+ curmove, num_checks+1, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ }
+ /* Late move reductions (LMR)
+ * The idea here is if a move occurs late in the movelist,
+ * it's probably not worth searching to a full depth (if it
+ * happens to return a value within the window, re-search with
+ * full depth). This works recursively, so strings of moves
+ * that are all Late get searched to (optimal case) 1/2 depth
+ * overall, while lines with just one Late move are searched
+ * with depth reduced by just one overall. What happens if we
+ * encounter a seemingly bad move that only pays off when
+ * searched to the full depth (i.e. sacrifice -> attack)?
+ * Typically, such lines will only have one or two Late moves
+ * in them, and we rely on the more extreme reductions on the
+ * completely nonsense lines (1/2-depth mentioned before) to
+ * possibly give us another ply so we find the sacrifice. */
+ else if (children_searched > lmr_movecount[nodetype] && depth > 3 &&
+ !MOV_CAPT(curmove) && !MOV_CAPT(prevmove))
+ {
+ alphabeta(board, -beta, -alpha, depth-2, ply+1,
+ curmove, num_checks, null_extended,
+ childnodetype[nodetype][1]);
+ /* oops, it fell within our window. full re-search */
+ if (-lastval > alpha)
+ {
+ alphabeta(board, -beta, -alpha, depth-1, ply+1,
+ curmove, num_checks, null_extended,
+ childnodetype[nodetype][1]);
+ }
+ }
+ else /* no extensions/reductions, regular search */
+ {
+ alphabeta(board, -beta, -alpha, depth-1, ply+1,
+ curmove, num_checks, null_extended,
+ childnodetype[nodetype][!!children_searched]);
+ }
+ board_undomove(board, curmove);
+ children_searched++;
+
+ if (-lastval > alpha)
+ {
+ alpha = -lastval;
+ returnmove = curmove;
+ /* we've gotten above the bottom of the window */
+ trans_flag = TRANS_FLAG_EXACT;
+ }
+ if (beta <= alpha)
+ {
+ /* oops, above the top of the window */
+ trans_flag = TRANS_FLAG_BETA;
+ #ifdef SEARCHER_USE_KILLERS
+ /* Not a killer if capture or castle */
+ if (!(MOV_CAPT(curmove)) && !(MOV_CASTLE(curmove)))
+ {
+ /* We found a killer move! Add it in... note
+ * we will never here cause duplicate killers
+ * because we would have tested this killer
+ * earlier and skipped this */
+ killer_index = 0;
+ while ((killers[ply][killer_index] != 0) &&
+ (killer_index < SEARCHER_NUM_KILLERS-1))
+ {
+ /* move to first empty killer slot,
+ * or if full replace at the end */
+ killer_index++;
+ }
+ killers[ply][killer_index] = curmove;
+ }
+ #endif
+ break;
+ }
+ }
+ movelist_destroy(&moves);
+ /* now we are done iterating; cleanup and exit this node. note, this
+ * label is here so we can skip over iteration if the bestmove/killers
+ * produce a cutoff */
+alphabeta_after_iteration:
+ /* The transposition table will get really sad if we choke all over it
+ * with bogus results from after we get cut off */
+ if (timeup)
+ {
+ return 0;
+ }
+ #ifdef SEARCHER_USE_KILLERS
+ /* okay we need to clear the killers for the children here */
+ memset(killers[ply+1], 0, (SEARCHER_NUM_KILLERS * sizeof(move_t)));
+ #endif
+ /* check if there were no legal moves */
+ if (children_searched)
+ {
+ /* this is the "typical case" function ending
+ * set the value so the calling function sees it properly */
+ lastval = alpha;
+ /* Don't add mates because they are depth-dependent. Don't add
+ * draws because they are state-dependent. */
+ if (!VALUE_ISMATE(alpha) && !VALUE_ISDRAW(alpha))
+ {
+ /* update the trans table - here we always replace */
+ trans_add(board->hash, returnmove, board->reps, alpha,
+ (board->moves + depth - cur_searching_depth),
+ board->moves, depth, trans_flag);
+ }
+ }
+ else /* no children were searched - must be an end condition */
+ {
+ /* checkmate vs stalemate */
+ if (board_incheck(board))
+ {
+ lastval = -1 * (SEARCHER_MATE - ply);
+ }
+ else
+ {
+ lastval = 0;
+ }
+ /* DON'T add to the transposition table here... this can screw
+ * up which mates are sooner and cause 3-rep draws - besides,
+ * if a mate is coming up and we've seen it there's no use
+ * trying to search deeper/faster */
+ return 0;
+ }
+ /* and we're done */
+ return returnmove;
+}
+/****************************************************************************
+ * transposition.c - avoid re-searching already searched positions
+ * copyright (C) 2008 Ben Blum
+ ****************************************************************************/
+
+typedef struct trans_entry_t {
+ uint64_t key;
+ trans_data_t value;
+} trans_entry_t;
+
+/**
+ * Statically initting the array is good because it avoids committing memory
+ * we don't use, but depends, for efficiency not correctness, on the kernel
+ * harbl-filling our memory with zeros. When we go to kick out an entry, if
+ * we haven't put one there yet, we'll see that the depth is 0 and the flag
+ * is ALPHA - the two worst possible values, so this type will always be
+ * replaced.
+ */
+#ifndef TRANS_NUM_BUCKETS
+#define TRANS_NUM_BUCKETS ((128 * 1024 * 1024)/sizeof(trans_entry_t)) // 128 MB
+#endif
+static trans_entry_t array[TRANS_NUM_BUCKETS];
+
+/**
+ * Convert separate data values -> condensed struct
+ */
+static trans_data_t trans_data(move_t move, uint8_t reps, int16_t value,
+ uint8_t gamedepth, uint8_t searchdepth,
+ uint8_t flag)
+{
+ trans_data_t foo;
+ assert(searchdepth < 64);
+ foo.move = move | (reps << MOV_INDEX_UNUSED);
+ foo.value = value;
+ foo.gamedepth = gamedepth;
+ foo.flags = ((searchdepth & 0x3f) << TRANS_INDEX_SEARCHDEPTH) |
+ ((flag & 0x3) << TRANS_INDEX_FLAG);
+ return foo;
+}
+
+/**
+ * Add transposition information to the table. Note, it will only kick the old
+ * entry out if:
+ * 1) The flag is higher (exact kicks out beta, beta kicks out alpha)
+ * 2) The flag is equal and the depth is higher
+ * 3) The old node was from ancient history
+ * Note the different depth arguments:
+ * rootdepth - how far down the game tree the real board state is.
+ * used in comparison for evicting the old node.
+ * gamedepth - how far down this current node is in the game tree. we
+ * store this for future nodes to use to evict us.
+ * searchdepth - how much deeper still we've searched this node. this
+ * tells how trustworthy the alpha value is.
+ * At present we don't discriminate based on repetition depth.
+ */
+void trans_add(zobrist_t key, move_t move, uint8_t reps, int16_t value,
+ uint8_t rootdepth, uint8_t gamedepth,
+ uint8_t searchdepth, uint8_t flag)
+{
+ unsigned long bucket;
+ trans_data_t old;
+
+ /* find the bucket */
+ bucket = key % TRANS_NUM_BUCKETS;
+
+ /* find what used to be there */
+ old = array[bucket].value;
+
+ /* see if we should evict */
+ if ((rootdepth >= TRANS_GAMEDEPTH(old)) || /* old node too old */
+ (flag > TRANS_FLAG(old)) || /* more accurate data */
+ ((flag == TRANS_FLAG(old)) && /* same type of data but... */
+ (searchdepth > TRANS_SEARCHDEPTH(old)))) /* ...deeper search */
+ {
+ /* so we set the stuff to our new node */
+ array[bucket].key = key;
+ array[bucket].value = trans_data(move, reps, value, gamedepth,
+ searchdepth, flag);
+ }
+ return;
+}
+
+/**
+ * Fetch data from the table. If there is no entry for this key the flag in
+ * the return value will be set to -1.
+ */
+static trans_data_t foo = { (uint8_t)(-1), (uint8_t)(-1),
+ (int16_t)(-1), (uint32_t)(-1) };
+trans_data_t trans_get(zobrist_t key)
+{
+ unsigned long bucket = key % TRANS_NUM_BUCKETS;
+ if (array[bucket].key == key)
+ {
+ return array[bucket].value;
+ }
+ return foo;
+}
+
+/**
+ * Check if the transposition data is valid, according to whatever spec may be
+ * in use for saying "invalid entry". Used for checking the returnvalue of get
+ */
+int trans_data_valid(trans_data_t foo)
+{
+ return (foo.flags != (uint8_t)(-1));
+}
+
+/******************************************************************************
+ * Custom pebbles interface
+ ******************************************************************************/
+
+/********************** BOARD / SCREEN CONTENT ********************************/
+
+char *board_strs[] = {
+ " a b c d e f g h ",
+ " .-------------------------------. ",
+ "8 | | | | | | | | | 8",
+ " |---+---+---+---+---+---+---+---| ",
+ "7 | | | | | | | | | 7",
+ " |---+---+---+---+---+---+---+---| ",
+ "6 | | | | | | | | | 6",
+ " |---+---+---+---+---+---+---+---| ",
+ "5 | | | | | | | | | 5",
+ " |---+---+---+---+---+---+---+---| ",
+ "4 | | | | | | | | | 4",
+ " |---+---+---+---+---+---+---+---| ",
+ "3 | | | | | | | | | 3",
+ " |---+---+---+---+---+---+---+---| ",
+ "2 | | | | | | | | | 2",
+ " |---+---+---+---+---+---+---+---| ",
+ "1 | | | | | | | | | 1",
+ " `-------------------------------' ",
+ " a b c d e f g h ",
+};
+char *board_strs_flipped[] = {
+ " h g f e d c b a ",
+ " .-------------------------------. ",
+ "1 | | | | | | | | | 1",
+ " |---+---+---+---+---+---+---+---| ",
+ "2 | | | | | | | | | 2",
+ " |---+---+---+---+---+---+---+---| ",
+ "3 | | | | | | | | | 3",
+ " |---+---+---+---+---+---+---+---| ",
+ "4 | | | | | | | | | 4",
+ " |---+---+---+---+---+---+---+---| ",
+ "5 | | | | | | | | | 5",
+ " |---+---+---+---+---+---+---+---| ",
+ "6 | | | | | | | | | 6",
+ " |---+---+---+---+---+---+---+---| ",
+ "7 | | | | | | | | | 7",
+ " |---+---+---+---+---+---+---+---| ",
+ "8 | | | | | | | | | 8",
+ " `-------------------------------' ",
+ " h g f e d c b a ",
+};
+#define BOARD_ROW 3 // the row of the opponent's sides lettering (a-h/h-a)
+#define BOARD_COL 4 // the col of the left side numbering (1-8/8-1)
+#define BOARD_ROW_SCALE 2
+#define BOARD_COL_SCALE 4
+
+#define BOARD_COLOR (FGND_BRWN | BGND_BLACK)
+#define WHITE_COLOR (FGND_WHITE | BGND_BLACK)
+#define BLACK_COLOR (FGND_RED | BGND_BLACK) // like the old-time chess sets
+
+int flipped = 0;
+int xyzzy = 0;
+
+void set_text_color(int color) {
+ int low = color & 0xf;
+ int high = color & ~0xf;
+ if (low == FGND_BLACK) {
+ set_term_color(color);
+ } else {
+ low = (low + xyzzy) & 0xf;
+ if (low == FGND_BLACK) low++;
+ set_term_color(low | high);
+ }
+}
+
+void draw_pieces(board_t *board, int color) {
+ int square;
+ bitboard_t pos;
+ int piece = PAWN;
+ while (piece <= KING) {
+ pos = board->pos[color][piece];
+ while (pos) {
+ int row_offset, col_offset;
+ square = BITSCAN(pos);
+ if (flipped) {
+ row_offset = BOARD_ROW_SCALE*(1 + ROW(square));
+ col_offset = BOARD_COL_SCALE*(8 - COL(square));
+ } else {
+ row_offset = BOARD_ROW_SCALE*(8 - ROW(square));
+ col_offset = BOARD_COL_SCALE*(1 + COL(square));
+ }
+ set_cursor_pos(BOARD_ROW + row_offset, BOARD_COL + col_offset);
+ print(1, piecename[color][piece]);
+ pos &= BB_ALLEXCEPT(square);
+ }
+ piece++;
+ }
+}
+
+// I'd say this should be called only on redraw, but it also has the
+// convenient effect of setting blank all unoccupied squares, which means
+// fewer syscalls overall... unless you'd like to analyse the board state
+// to determine what the most recently vacated square is.... etc.
+void draw_board(board_t *board) {
+ unsigned int i;
+ set_text_color(BOARD_COLOR);
+ if (flipped) {
+ for (i = 0; i < ARRAY_SIZE(board_strs_flipped); i++) {
+ set_cursor_pos(BOARD_ROW+i, BOARD_COL);
+ print(strlen(board_strs_flipped[i]), board_strs_flipped[i]);
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(board_strs); i++) {
+ set_cursor_pos(BOARD_ROW+i, BOARD_COL);
+ print(strlen(board_strs[i]), board_strs[i]);
+ }
+ }
+ set_text_color(WHITE_COLOR);
+ draw_pieces(board, WHITE);
+ set_text_color(BLACK_COLOR);
+ draw_pieces(board, BLACK);
+}
+
+enum player_mode {
+ bot_black = 0,
+ bot_white = 1,
+ human = 2,
+};
+char *player_strs[] = {
+ "you vs bistromath",
+ "bistromath vs you",
+ " you vs yourself ",
+};
+#define PLAYERSTR_ROW 1
+#define PLAYERSTR_COL 14
+#define PLAYERSTR_COLOR (FGND_BBLUE | BGND_BLACK)
+
+enum player_mode player_mode = bot_black;
+
+void draw_player_str() {
+ set_text_color(PLAYERSTR_COLOR);
+ set_cursor_pos(PLAYERSTR_ROW, PLAYERSTR_COL);
+ assert(player_mode < ARRAY_SIZE(player_strs));
+ print(strlen(player_strs[player_mode]),
+ player_strs[player_mode]);
+}
+
+#define STATUS_WHITEMOVE " [white to move] "
+#define STATUS_BLACKMOVE " [black to move] "
+#define STATUS_WHITEMATE " [0-1 white checkmated] "
+#define STATUS_BLACKMATE " [1-0 black checkmated] "
+#define STATUS_WHITERESIGN " [0-1 white resigns] "
+#define STATUS_BLACKRESIGN " [1-0 black resigns] "
+#define STATUS_DRAW3MOVE " [1/2-1/2 game drawn by 3-fold repetition] "
+#define STATUS_DRAW50MOVE " [1/2-1/2 game drawn by 50 move rule] "
+#define STATUS_DRAWSTALE " [1/2-1/2 game drawn by stalemate] "
+#define STATUS_DRAWNOMATE "[1/2-1/2 neither side has mating material]"
+
+#define STATUS_ROW 23
+#define STATUS_COL 1
+#define STATUS_COLOR (FGND_BBLUE | BGND_BLACK)
+
+char *status_str = STATUS_WHITEMOVE;
+
+// gentleperson's agreement: msg must be one of the predefined ones above
+void draw_status_str() {
+ assert(strlen(status_str) == strlen(STATUS_WHITEMOVE));
+ set_text_color(STATUS_COLOR);
+ set_cursor_pos(STATUS_ROW, STATUS_COL);
+ print(strlen(status_str), status_str);
+}
+
+/************************* CONSOLE LIBRARY ************************************/
+
+char *helptext[] = {
+ "Commands available: ",
+ "a2a4 - move (e.g.) ", //
+ "e7e8Q - move with pawn promote ", //
+ "go - switch sides; bot goes ", //
+ "human - let two people play ", //
+ "flip - turn the board around ", //
+ "new - start a new game ", //
+ "quiet - don't think out loud ", //
+ "loud - think out loud ", //
+ "hint - what the bot would do ", //
+ "undo - take back a move ", //
+ "resign - give up ", //
+ "depth - set/show difficulty ", //
+ "time - set search time limit ",
+ "book - turn on/off opening book", //
+ "credit - show credit info ", //
+ "help - show this ", //
+ "quit - quit ", //
+ "Sorry no algebraic move syntax. ",
+};
+
+char *credittext[] = {
+ "\"Bistromath\" is (C) 2013 Ben Blum",
+ "Originally written 2008 ",
+ "Engine finished 2010 ",
+ "Ported to Pebbles 2012 ",
+ "Questions/bugs? bblum@cs.cmu.edu",
+ "(type \"help\" for commands) ",
+};
+
+#define CONSOLE_HEIGHT 25
+#define CONSOLE_WIDTH 80
+
+// these defines could be a little more flexible
+#define TEXT_WIDTH 34 // custom console dimensions
+#define TEXT_HEIGHT (CONSOLE_HEIGHT-2)
+#define TEXT_ROW 0 // where the custom console's top left corner is
+#define TEXT_COL (CONSOLE_WIDTH-TEXT_WIDTH)
+char textconsole[TEXT_HEIGHT][TEXT_WIDTH];
+#define PROMPT "> "
+#define TEXT_COLOR (FGND_GREEN | BGND_BLACK)
+#define PROMPT_COLOR (FGND_BGRN | BGND_BLACK)
+
+void init_console() {
+ int i, j;
+ for (i = 0; i < TEXT_HEIGHT; i++) { for (j = 0; j < TEXT_WIDTH; j++) {
+ textconsole[i][j] = ' ';
+ }}
+}
+
+// Printing e.g. help text would be more efficient with a print n lines function
+// Future work! At least draw_console is separated out.
+void print_line(const char *buf, unsigned int len) {
+ if (len > TEXT_WIDTH) len = TEXT_WIDTH;
+ /* Scroll. */
+ int i;
+ for (i = 1; i < TEXT_HEIGHT; i++) {
+ strncpy(textconsole[i-1], textconsole[i], TEXT_WIDTH);
+ }
+ /* Command prompt always stays on the bottom. */
+ strncpy(textconsole[TEXT_HEIGHT-1], buf, len);
+ /* Pad rest of line with whitespace */
+ for (i = len; i < TEXT_WIDTH; i++) {
+ textconsole[TEXT_HEIGHT-1][i] = ' ';
+ }
+}
+
+// Flush, essentially
+void draw_console() {
+ int i;
+ set_text_color(TEXT_COLOR);
+ for (i = 0; i < TEXT_HEIGHT; i++) {
+ set_cursor_pos(TEXT_ROW + i, TEXT_COL);
+ print(TEXT_WIDTH, textconsole[i]);
+ }
+}
+void draw_prompt() {
+ char buf[TEXT_WIDTH+1]; // Trac ticket #157. ARGGH
+ set_text_color(PROMPT_COLOR);
+ set_cursor_pos(TEXT_ROW + TEXT_HEIGHT, TEXT_COL);
+ assert(strlen(PROMPT) < TEXT_WIDTH);
+ snprintf(buf, TEXT_WIDTH, "%s%*s", PROMPT, TEXT_WIDTH-strlen(PROMPT), " ");
+ buf[TEXT_WIDTH-1] = 0; // Trac ticket #157. ARGGH
+ print(TEXT_WIDTH, buf);
+ set_cursor_pos(TEXT_ROW + TEXT_HEIGHT, TEXT_COL + strlen(PROMPT));
+}
+
+
+// for other modules of the engine to print
+int outbuf_size = TEXT_WIDTH;
+char outbuf[TEXT_WIDTH];
+void output() { print_line(outbuf, TEXT_WIDTH); draw_console(); }
+
+/**************************** MAIN ROUTINES ***********************************/
+
+int text_loud = 1;
+
+void help() {
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(helptext); i++) {
+ print_line(helptext[i], strlen(helptext[i]));
+ }
+}
+void credits() {
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(credittext); i++) {
+ print_line(credittext[i], strlen(credittext[i]));
+ }
+}
+
+void redraw(board_t *board) {
+ // clear screen
+ int i;
+ char spaces[CONSOLE_WIDTH+1]; // Trac ticket #157. ARGGH
+ snprintf(spaces, CONSOLE_WIDTH, "%*s", CONSOLE_WIDTH, " ");
+ spaces[CONSOLE_WIDTH-1] = 0; // Trac ticket #157. ARGGH
+ set_text_color(FGND_BLACK | BGND_BLACK); // erase existing bgnd
+ for (i = 0; i < CONSOLE_HEIGHT; i++) {
+ set_cursor_pos(i, 0);
+ print(CONSOLE_WIDTH, spaces);
+ }
+ // draw everything
+ draw_board(board);
+ draw_player_str();
+ draw_status_str();
+ draw_console();
+ draw_prompt();
+}
+
+engine_t *e;
+int gameover = 0;
+
+int checkgameover() {
+ int matetype;
+ if (e->board->halfmoves >= 100) {
+ status_str = STATUS_DRAW50MOVE;
+ return 1;
+ } else if (board_threefold_draw(e->board)) {
+ status_str = STATUS_DRAW3MOVE;
+ return 1;
+ }
+ /* Resignation is handled elsewhere */
+ matetype = board_mated(e->board);
+ /* check if a player is mated */
+ if (matetype == BOARD_CHECKMATED) {
+ status_str = e->board->tomove == WHITE ? STATUS_WHITEMATE
+ : STATUS_BLACKMATE;
+ return 1;
+ } else if (matetype == BOARD_STALEMATED) {
+ status_str = STATUS_DRAWSTALE;
+ return 1;
+ } else if ((e->board->material[BLACK] == 0 && // Both players have 0
+ e->board->material[WHITE] == 0) ||
+ (e->board->material[BLACK] == 0 && // B has 0, W has N or B
+ ((e->board->material[WHITE] == eval_piecevalue[BISHOP] &&
+ e->board->pos[WHITE][BISHOP] != BB(0x0)) ||
+ (e->board->material[WHITE] == eval_piecevalue[KNIGHT] &&
+ e->board->pos[WHITE][KNIGHT] != BB(0x0)))) ||
+ (e->board->material[WHITE] == 0 && // W has 0, B has N or B
+ ((e->board->material[BLACK] == eval_piecevalue[BISHOP] &&
+ e->board->pos[BLACK][BISHOP] != BB(0x0)) ||
+ (e->board->material[BLACK] == eval_piecevalue[KNIGHT] &&
+ e->board->pos[BLACK][KNIGHT] != BB(0x0))))) {
+ status_str = STATUS_DRAWNOMATE;
+ return 1;
+ } else {
+ status_str = e->board->tomove == WHITE ? STATUS_WHITEMOVE
+ : STATUS_BLACKMOVE;
+ return 0;
+ }
+}
+
+void makemove() {
+ draw_prompt();
+ // TODO: Spawn a separate thread that can interrupt... somehow?
+ char *str = engine_generatemove(e);
+ char *errmsg;
+ int x = engine_applymove(e, str, &errmsg);
+ affirm_msg(x, "engine_generatemove() generated an illegal move");
+ free(str);
+}
+
+#define INBUF_LEN (2*TEXT_WIDTH)
+static inline void print_string(const char *s) { print_line(s, strlen(s)); }
+
+int main() {
+ thr_init(4096);
+ e = engine_init(getbestmove);
+ char inbuf[INBUF_LEN];
+ char *nogame = "No game is in progress.";
+ assert(e != NULL);
+ {
+ int i;
+ init_console();
+ credits();
+ for (i = ARRAY_SIZE(credittext); i < TEXT_HEIGHT; i++) {
+ print_line("", 0);
+ }
+ redraw(e->board);
+ }
+ while(1) {
+ int ret, need_redraw = 0;
+ char inbuf2[TEXT_WIDTH];
+ memset(inbuf, 0, sizeof(inbuf));
+ ret = readline(INBUF_LEN-1, inbuf);
+ affirm_msg(ret >= 0, "readline() failed");
+ if (inbuf[strlen(inbuf)-1] == '\n') {
+ inbuf[strlen(inbuf)-1] = '\0';
+ }
+ if (strlen(inbuf) > TEXT_WIDTH-strlen(PROMPT)) {
+ need_redraw = 1;
+ snprintf(inbuf + TEXT_WIDTH - strlen(PROMPT) - 3,
+ 3, "...");
+ }
+ /* echo user command */
+ snprintf(inbuf2, TEXT_WIDTH, "%s%s", PROMPT, inbuf);
+ print_line(inbuf2, strlen(inbuf2));
+ /* process command */
+ if (0 == strcmp(inbuf, "quit") || 0 == strcmp(inbuf, "exit")) {
+ set_cursor_pos(CONSOLE_HEIGHT, 0);
+ engine_destroy(e);
+ thr_exit(0);
+ return 0;
+ /* Misc management */
+ } else if (0 == strcmp(inbuf, "help")) {
+ help();
+ } else if (0 == strcmp(inbuf, "credit")) {
+ credits();
+ } else if (0 == strcmp(inbuf, "loud")) {
+ if (text_loud) {
+ print_string("This is as loud as I can be!");
+ } else {
+ print_string("Will now think out loud.");
+ text_loud = 1;
+ }
+ } else if (0 == strcmp(inbuf, "quiet")) {
+ if (!text_loud) {
+ print_string("You don't need to ask twice.");
+ } else {
+ print_string("OK, I'll keep it to myself.");
+ text_loud = 0;
+ }
+ } else if (0 == strcmp(inbuf, "flip")) {
+ flipped = !flipped;
+ if (!need_redraw) draw_board(e->board);
+ } else if (0 == strcmp(inbuf, "book")) {
+ book_enabled = !book_enabled;
+ if (book_enabled) {
+ print_string("Opening book on.");
+ e->inbook = 1;
+ } else {
+ print_string("Opening book off.");
+ }
+ /* Easter eggs */
+ } else if (0 == strncmp(inbuf, "punch", 5) ||
+ 0 == strncmp(inbuf, "kill", 4)) {
+ print_string("Keep your mind on the game.");
+ } else if (0 == strncmp(inbuf, "hug", 3)) {
+ print_string("If you think that'll help.");
+ } else if (0 == strncmp(inbuf, "look", 4) ||
+ 0 == strcmp(inbuf, "north") || 0 == strcmp(inbuf, "n") ||
+ 0 == strcmp(inbuf, "east") || 0 == strcmp(inbuf, "e") ||
+ 0 == strcmp(inbuf, "south") || 0 == strcmp(inbuf, "s") ||
+ 0 == strcmp(inbuf, "west") || 0 == strcmp(inbuf, "w")) {
+ print_string("This isn't that kind of game.");
+ } else if (0 == strcmp(inbuf, "inventory")) {
+ print_string("Nothing. This isn't bughouse.");
+ } else if (0 == strcmp(inbuf, "ls")) {
+ print_string("I'll pretend you didn't say that.");
+ } else if (0 == strcmp(inbuf, "xyzzy")) {
+ xyzzy++;
+ if (xyzzy == 0x10) xyzzy = 0;
+ need_redraw = 1;
+ /* Game management */
+ } else if (0 == strcmp(inbuf, "resign")) {
+ // Future feature: ask "are you sure?" (also on "new")
+ if (gameover) {
+ print_string(nogame);
+ } else {
+ print_string("I'm sorry it had to be that way.");
+ gameover = 1;
+ status_str = e->board->tomove == WHITE ?
+ STATUS_WHITERESIGN : STATUS_BLACKRESIGN;
+ draw_status_str();
+ }
+ } else if (0 == strcmp(inbuf, "hint")) {
+ trans_data_t trans_data = trans_get(e->board->hash);
+ if (gameover) {
+ print_string(nogame);
+ } else if (trans_data_valid(trans_data)) {
+ char *move = move_tostring(TRANS_MOVE(trans_data));
+ static unsigned int hint_index = 0;
+ const char *words[] =
+ { "Consider %s.", "Why not %s?",
+ "How do you feel about %s?",
+ "If it were me, I'd play %s." };
+ snprintf(inbuf2, TEXT_WIDTH,
+ words[hint_index++ % ARRAY_SIZE(words)],
+ move);
+ print_line(inbuf2, strlen(inbuf2));
+ free(move);
+ } else {
+ print_string("You're on your own here.");
+ }
+ } else if (0 == strcmp(inbuf, "new")) {
+ gameover = 0;
+ flipped = 0;
+ player_mode = bot_black;
+ status_str = STATUS_WHITEMOVE;
+ engine_destroy(e);
+ e = engine_init(getbestmove);
+ assert(e != NULL);
+ need_redraw = 1;
+ } else if (0 == strcmp(inbuf, "human")) {
+ if (gameover) {
+ print_string(nogame);
+ } else {
+ player_mode = human;
+ if (!need_redraw) draw_player_str();
+ }
+ } else if (0 == strncmp(inbuf, "depth", 5)) {
+ // See trac bug #73. Argghhhh.
+ char *endp;
+ unsigned int n = strtol(&inbuf[6], &endp, 0);
+ assert(searcher_max_depth < SEARCHER_MAX_DEPTH);
+ assert(searcher_max_depth >= SEARCHER_MIN_DEPTH);
+ if (inbuf[5] != ' ' || endp == &inbuf[6]) {
+ print_string("Use \"depth N\" to limit max depth.");
+ snprintf(inbuf2, TEXT_WIDTH, "Currently %u (0 = no limit)",
+ searcher_max_depth == SEARCHER_MAX_DEPTH-1 ?
+ 0 : searcher_max_depth);
+ print_string(inbuf2);
+ } else {
+ if (n >= SEARCHER_MAX_DEPTH || n == 0)
+ n = SEARCHER_MAX_DEPTH-1;
+ else if (n < SEARCHER_MIN_DEPTH)
+ n = SEARCHER_MIN_DEPTH;
+ searcher_max_depth = n;
+ print_string("OK.");
+ }
+ } else if (0 == strncmp(inbuf, "time", 4)) {
+ // Argghhhh, as above.
+ char *endp;
+ unsigned int n = strtol(&inbuf[5], &endp, 0);
+ assert(searchtime >= 1);
+ assert(searchtime <= SEARCHTIME_MAX);
+ if (inbuf[4] != ' ' || endp == &inbuf[5]) {
+ print_string("Use \"time N\" to limit search time.");
+ snprintf(inbuf2, TEXT_WIDTH, "Currently %u (max %u)",
+ searchtime, SEARCHTIME_MAX);
+ print_string(inbuf2);
+ } else {
+ if (n > SEARCHTIME_MAX || n == 0)
+ n = SEARCHTIME_DEFAULT;
+ searchtime = n;
+ print_string("OK.");
+ }
+ } else if (0 == strcmp(inbuf, "undo")) {
+ const char *words1[] =
+ { "We're at the beginning already.",
+ "My memories are hazy before this.",
+ "Stop, you're making me dizzy.",
+ "Can't take tail of empty list." };
+ static unsigned int undo_index = 0;
+ const char *words2[] =
+ { "Be more careful next time.",
+ "I won't judge you; I'm a computer.",
+ "Sure, as if time travel is easy.",
+ "You're pushing your luck, kiddo.",
+ "Next you'll ask for lessons?",
+ };
+ static unsigned int undo_index2 = 0;
+ if (e->board->moves == 0) {
+ print_string(gameover ?
+ "Just accept it and move on." :
+ words1[undo_index++ % ARRAY_SIZE(words1)]);
+ } else {
+ engine_undomove(e);
+ if (player_mode == bot_white)
+ player_mode = bot_black;
+ else if (player_mode == bot_black)
+ player_mode = bot_white;
+ flipped = !flipped;
+ gameover = checkgameover(); // refresh status string
+ assert(!gameover && "Game over after undo??");
+ if (!need_redraw) draw_player_str();
+ if (!need_redraw) draw_board(e->board);
+ if (!need_redraw) draw_status_str();
+ print_string(words2[undo_index2++ %
+ ARRAY_SIZE(words2)]);
+ }
+ /* Moving */
+ } else if (0 == strcmp(inbuf, "go")) {
+ if (gameover) {
+ print_string(nogame);
+ } else {
+ player_mode = e->board->tomove == WHITE ?
+ bot_white : bot_black;
+ flipped = !flipped;
+ if (!need_redraw) draw_player_str();
+ if (!need_redraw) draw_board(e->board);
+ makemove();
+ if (!need_redraw) draw_board(e->board);
+ gameover = checkgameover();
+ if (!need_redraw) draw_status_str();
+ }
+ } else if (!!move_fromstring(inbuf)) {
+ char *errmsg = NULL;
+ if (gameover) {
+ print_string(nogame);
+ } else if (engine_applymove(e, inbuf, &errmsg)) {
+ if ((gameover = checkgameover())) {
+ print_string("Good game!");
+ } else if (player_mode != human) {
+ /* Make a move in response. */
+ if (!need_redraw) draw_status_str();
+ if (!need_redraw) draw_board(e->board);
+ makemove();
+ if (!need_redraw) draw_board(e->board);
+ if ((gameover = checkgameover())) {
+ print_string("Good game!");
+ }
+ } else {
+ flipped = !flipped;
+ if (!need_redraw) draw_board(e->board);
+ }
+ if (!need_redraw) draw_status_str();
+ } else {
+ assert(errmsg != NULL);
+ print_string(errmsg);
+ }
+ /* Fail */
+ } else {
+ print_string(strlen(inbuf) ? "I didn't understand that." :
+ "You'll have to be more specific.");
+ }
+ /* Update display to reflect changes */
+ if (need_redraw) {
+ redraw(e->board);
+ } else {
+ draw_console();
+ draw_prompt();
+ }
+ }
+ panic("completed infinite loop!");
+ return 31337;
+}
diff --git a/410user/progs/cat.c b/410user/progs/cat.c
new file mode 100644
index 0000000..9d2ef97
--- /dev/null
+++ b/410user/progs/cat.c
@@ -0,0 +1,30 @@
+// Simple program to print out files.
+// Michael J. Sullivan, Spring 2013
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define BUFSIZE 87 // "four score and seven"
+
+int main(int argc, char **argv)
+{
+ char buf[BUFSIZE];
+ int i;
+ for (i = 1; i < argc; i++) {
+ char *file = argv[i];
+ int offset = 0;
+ int amt_read;
+ while ((amt_read = readfile(file, buf, BUFSIZE, offset)) > 0) {
+ print(amt_read, buf);
+ offset += amt_read;
+ }
+ if (amt_read < 0) {
+ printf("error reading from file %s at offset %d\n",
+ file, offset);
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/410user/progs/cho.c b/410user/progs/cho.c
new file mode 100644
index 0000000..2270a75
--- /dev/null
+++ b/410user/progs/cho.c
@@ -0,0 +1,103 @@
+/** @file 410user/progs/cho.c
+ * @author de0u
+ * @brief "Continuous hours of operation" - runs many tests.
+ * @public yes
+ * @for p3
+ * @covers fork exec wait set_status vanish sleep
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("cho:");
+
+/* Every UPDATE_FREQUENCY reaps, print out an update of
+ * how many children of each type are left.
+ */
+#define UPDATE_FREQUENCY 50
+
+#define SERIOUSLY_DEAD (0xdeaddead)
+
+struct prog {
+ char *name;
+ int pid;
+ int count;
+} progs[] = {
+ {"sleep_test1", -1, 13},
+ {"wait_getpid", -1, 100},
+ {"wild_test1", -1, 100},
+ {"exec_basic", -1, 100},
+ {"print_basic", -1, 100}
+};
+
+int main()
+{
+ int active_progs = sizeof (progs) / sizeof (progs[0]);
+ int active_processes = 0;
+ struct prog *p, *fence;
+ int reap_count = 0;
+
+ report_start(START_CMPLT);
+ TEST_PROG_ENGAGE(300);
+
+ fence = progs + active_progs;
+
+ while ((active_progs > 0) || (active_processes > 0)) {
+
+ /* launch some processes */
+ for (p = progs; p < fence; ++p) {
+ if ((p->count > 0) && (p->pid == -1)) {
+ int pid = fork();
+
+ if (pid < 0) {
+ sleep(1);
+ } else if (pid == 0) {
+ char *args[2];
+
+ report_misc("After fork(): I am a child!");
+ TEST_PROG_PROGRESS;
+
+ args[0] = p->name;
+ args[1] = 0;
+ exec(p->name, args);
+ report_misc("exec() failed (missing object?)");
+ report_end(END_FAIL);
+ exit(SERIOUSLY_DEAD);
+ } else {
+ p->pid = pid;
+ ++active_processes;
+ }
+ }
+ }
+
+ /* reap a child */
+ if (active_processes > 0) {
+ int pid, status;
+ pid = wait(&status);
+ if (status == SERIOUSLY_DEAD)
+ exit(SERIOUSLY_DEAD);
+ report_fmt("wait() done: %d with status %d", pid, status);
+ TEST_PROG_PROGRESS;
+ ++reap_count;
+ for (p = progs; p < fence; ++p) {
+ if (p->pid == pid) {
+ p->pid = -1;
+ --p->count;
+ if (p->count <= 0)
+ --active_progs;
+ --active_processes;
+ }
+ if (reap_count % UPDATE_FREQUENCY == 0) {
+ report_fmt("%s: %d left", p->name, p->count);
+ }
+ }
+ }
+ }
+
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/cho2.c b/410user/progs/cho2.c
new file mode 100644
index 0000000..178ebad
--- /dev/null
+++ b/410user/progs/cho2.c
@@ -0,0 +1,108 @@
+/** @file 410user/progs/cho2.c
+ * @author de0u
+ * @author ctokar
+ * @brief "Continuous hours of operation" - run many tests.
+ * @public yes
+ * @for p3
+ * @covers fork exec wait gettid set_status vanish sleep
+ * @todo Progress checking?
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <simics.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("cho2:");
+
+/* Every UPDATE_FREQUENCY reaps, print out an update of
+ * how many children of each type are left.
+ */
+#define UPDATE_FREQUENCY 50
+
+#define SERIOUSLY_DEAD (0xdeaddead)
+
+struct prog {
+ char *name;
+ int pid;
+ int count;
+} progs[] = {
+ {"getpid_test1", -1, 13},
+ {"yield_desc_mkrun", -1, 100},
+ {"remove_pages_test1", -1, 100},
+ {"loader_test1", -1, 100},
+ {"fork_wait", -1, 100},
+ {"swexn_rampage", -1, 1},
+ {"mem_permissions", -1, 31},
+ {"minclone_mem", -1, 17}
+};
+
+int main()
+{
+ int active_progs = sizeof (progs) / sizeof (progs[0]);
+ int active_processes = 0;
+ struct prog *p, *fence;
+ int reap_count = 0;
+
+ report_start(START_CMPLT);
+ TEST_PROG_ENGAGE(300);
+
+ fence = progs + active_progs;
+
+ while ((active_progs > 0) || (active_processes > 0)) {
+
+ /* launch some processes */
+ for (p = progs; p < fence; ++p) {
+ if ((p->count > 0) && (p->pid == -1)) {
+ int pid = fork();
+
+ if (pid < 0) {
+ sleep(1);
+ } else if (pid == 0) {
+ char *args[2];
+
+ report_misc("After fork(): I am a child!");
+ TEST_PROG_PROGRESS;
+
+ args[0] = p->name;
+ args[1] = 0;
+ exec(p->name, args);
+ report_misc("exec() failed (missing object?)");
+ report_end(END_FAIL);
+ exit(SERIOUSLY_DEAD);
+ } else {
+ p->pid = pid;
+ ++active_processes;
+ }
+ }
+ }
+
+ /* reap a child */
+ if (active_processes > 0) {
+ int pid, status;
+ pid = wait(&status);
+ if (status == SERIOUSLY_DEAD)
+ exit(SERIOUSLY_DEAD);
+ report_fmt("wait() done: %d with status %d", pid, status);
+ TEST_PROG_PROGRESS;
+ ++reap_count;
+ for (p = progs; p < fence; ++p) {
+ if (p->pid == pid) {
+ p->pid = -1;
+ --p->count;
+ if (p->count <= 0)
+ --active_progs;
+ --active_processes;
+ }
+ if (reap_count % UPDATE_FREQUENCY == 0) {
+ report_fmt("%s: %d left", p->name, p->count);
+ }
+ }
+ }
+ }
+
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/cho_variant.c b/410user/progs/cho_variant.c
new file mode 100644
index 0000000..4485f00
--- /dev/null
+++ b/410user/progs/cho_variant.c
@@ -0,0 +1,171 @@
+/** @file 410user/progs/cho_variant.c
+ * @author de0u
+ * @author ctokar
+ * @author nwf
+ * @brief "Continuous hours of operation" - runs many tests.
+ * @public yes
+ * @for p3
+ * @covers fork exec wait set_status vanish sleep remove_pages new_pages
+ * @covers deschedule make_runnable yield
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("cho_variant:");
+
+/** @brief Every UPDATE_FREQUENCY reaps, print out an update of
+ * how many children of each type are left.
+ */
+static const int UPDATE_FREQUENCY = 10;
+
+/** @brief Error signaling return code.
+ * @pre Ensure that no test program in the table below returns this
+ * constant.
+ */
+static const int DEAD_TEST_PROGRAM_RETURN = 0xDEADDEAD;
+
+/** @brief Program table */
+struct prog {
+ char *name;
+ int expected;
+ int pid;
+ int count;
+} progs[]
+ = {
+ {"exec_basic", 1, -1, 5},
+ {"fork_wait", 0, -1, 5},
+ {"loader_test1", 0, -1, 5},
+ {"loader_test2", 42, -1, 5},
+ {"make_crash",10000,-1, 1},
+ {"print_basic",0,-1,5},
+ {"remove_pages_test1", 0, -1, 2},
+ {"remove_pages_test2", -2, -1, 5}, /* Should die: wild pointer */
+ {"sleep_test1", 42, -1, 5}, /* indistinguishible outcomes */
+ {"stack_test1", 42, -1, 5},
+ {"wild_test1", -2, -1, 5}, /* Should die: wild pointer */
+ {"yield_desc_mkrun", 0, -1, 5},
+};
+
+int main(int argc, char **argv)
+{
+ int active_progs = sizeof (progs) / sizeof (progs[0]);
+ int active_processes = 0;
+ struct prog *p, *fence;
+ int reap_count = 0;
+ int matched;
+ int magic_break = 0;
+
+ if ( argc > 1 )
+ {
+ if ( !strcmp("MAGIC", argv[1]) )
+ {
+ magic_break = 1;
+ }
+ }
+
+ report_start(START_CMPLT);
+ TEST_PROG_ENGAGE(1200);
+
+ fence = progs + active_progs;
+
+ while ((active_progs > 0) || (active_processes > 0)) {
+
+ /* launch some processes */
+ for (p = progs; p < fence; ++p) {
+ if ((p->count > 0) && (p->pid == -1)) {
+ int pid = fork();
+
+ if (pid < 0) {
+ sleep(1);
+ } else if (pid == 0) {
+ char *args[2];
+
+ report_fmt("after fork(): I am a child (prog %s, tid %d)",
+ p->name, gettid());
+ TEST_PROG_PROGRESS;
+
+ args[0] = p->name;
+ args[1] = 0;
+ exec(p->name, args);
+ report_misc("exec() failed");
+ /* Leave it to the parent to emit the test failure message */
+ if ( magic_break )
+ {
+ MAGIC_BREAK;
+ }
+ exit(DEAD_TEST_PROGRAM_RETURN);
+ } else {
+ p->pid = pid;
+ ++active_processes;
+ }
+ }
+ }
+
+ /* reap a child */
+ if (active_processes > 0) {
+ int pid, status;
+ pid = wait(&status);
+ if (status == DEAD_TEST_PROGRAM_RETURN)
+ {
+ lprintf("%s%s%s", TEST_PFX,test_name,TEST_END_FAIL);
+ if ( magic_break )
+ {
+ MAGIC_BREAK;
+ }
+ exit(-1);
+ }
+ TEST_PROG_PROGRESS;
+ ++reap_count;
+ for (p = progs, matched = 0; p < fence; ++p) {
+ if (p->pid == pid) {
+ matched = 1;
+ lprintf("%s%s After wait(): pid = %d, prog = %s",
+ TEST_PFX, test_name, pid, p->name);
+ if ( status != p->expected )
+ {
+ lprintf("=( TEST FAILED: %s; EXPECT %d GOT %d",
+ p->name, p->expected, status );
+ lprintf("%s%s%s", TEST_PFX,test_name,TEST_END_FAIL);
+ if ( magic_break )
+ {
+ MAGIC_BREAK;
+ }
+ exit(-1);
+ }
+ p->pid = -1;
+ --p->count;
+ if (p->count <= 0)
+ --active_progs;
+ --active_processes;
+ }
+ if (reap_count % UPDATE_FREQUENCY == 0)
+ {
+ /* Display progress on softcons as well, in condensed form */
+ report_fmt("%s: %d left", p->name, p->count);
+ printf("[%s,%d]",p->name, p->count);
+ }
+ }
+ if ( matched == 0 )
+ {
+ report_fmt("unexpected waited pid %d (status %d)", pid, status);
+ report_end(END_FAIL);
+ if ( magic_break )
+ {
+ MAGIC_BREAK;
+ }
+ exit(-1);
+ }
+ }
+ if (reap_count % UPDATE_FREQUENCY == 0)
+ print(1, "\n");
+ }
+
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/chow.c b/410user/progs/chow.c
new file mode 100644
index 0000000..e0c4e02
--- /dev/null
+++ b/410user/progs/chow.c
@@ -0,0 +1,142 @@
+/** @file 410user/progs/chow.c
+ * @author acrichto
+ * @brief "Continuous hours of operation (work)" -
+ * runs a bunch of user-space code, not just syscalls
+ * @public yes
+ * @for p4-smp
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("chow:");
+
+/* Every UPDATE_FREQUENCY reaps, print out an update of
+ * how many children of each type are left.
+ */
+#define UPDATE_FREQUENCY 50
+
+#define SERIOUSLY_DEAD (0xdeaddead)
+
+struct prog {
+ char *name;
+ int pid;
+ int count;
+} progs[] = {
+ {"fib", -1, 20},
+ {"ack", -1, 20},
+ {"yield_desc_mkrun", -1, 100},
+ {"fork_wait", -1, 100}
+};
+
+char numbers[10][5][10] = {
+ {" ___ ", " / _ \\ ", "| | | |", "| |_| |", " \\___/ "},
+ {" _ ", "/ |", "| |", "| |", "|_|"},
+ {" ____ ", "|___ \\ ", " __) |", " / __/ ", "|_____|"},
+ {" _____ ", "|___ / ", " |_ \\ ", " ___) |", "|____/ "},
+ {" _ _ ", "| || | ", "| || |_ ", "|__ _|", " |_| "},
+ {" ____ ", "| ___| ", "|___ \\ ", " ___) |", "|____/ "},
+ {" __ ", " / /_ ", "| '_ \\ ", "| (_) |", " \\___/ "},
+ {" _____ ", "|___ |", " / / ", " / / ", " /_/ "},
+ {" ___ ", " ( _ ) ", " / _ \\ ", "| (_) |", " \\___/ "},
+ {" ___ ", " / _ \\ ", "| (_) |", " \\__, |", " /_/ "},
+};
+
+int main()
+{
+ int active_progs = sizeof (progs) / sizeof (progs[0]);
+ int active_processes = 0;
+ struct prog *p, *fence;
+ int reap_count = 0;
+
+ report_start(START_CMPLT);
+ TEST_PROG_ENGAGE(1200);
+
+ fence = progs + active_progs;
+ int ticks = get_ticks();
+
+ while ((active_progs > 0) || (active_processes > 0)) {
+
+ /* launch some processes */
+ for (p = progs; p < fence; ++p) {
+ if ((p->count > 0) && (p->pid == -1)) {
+ int pid = fork();
+
+ if (pid < 0) {
+ sleep(1);
+ } else if (pid == 0) {
+ char *args[2];
+
+ report_misc("After fork(): I am a child!");
+ TEST_PROG_PROGRESS;
+
+ args[0] = p->name;
+ args[1] = 0;
+ exec(p->name, args);
+ report_misc("exec() failed (missing object?)");
+ report_end(END_FAIL);
+ exit(SERIOUSLY_DEAD);
+ } else {
+ p->pid = pid;
+ ++active_processes;
+ }
+ }
+ }
+
+ /* reap a child */
+ if (active_processes > 0) {
+ int pid, status;
+ pid = wait(&status);
+ if (status == SERIOUSLY_DEAD)
+ exit(SERIOUSLY_DEAD);
+ report_fmt("wait() done: %d with status %d", pid, status);
+ TEST_PROG_PROGRESS;
+ ++reap_count;
+ for (p = progs; p < fence; ++p) {
+ if (p->pid == pid) {
+ p->pid = -1;
+ --p->count;
+ if (p->count <= 0)
+ --active_progs;
+ --active_processes;
+ }
+ if (reap_count % UPDATE_FREQUENCY == 0) {
+ report_fmt("%s: %d left", p->name, p->count);
+ }
+ }
+ }
+ }
+
+ ticks = get_ticks() - ticks;
+
+ int pow = 10;
+ while (pow * 10 < ticks) pow *= 10;
+
+ printf("\n"
+ "*****************************************************************\n"
+ "\n"
+ " Total ticks taken\n"
+ "\n");
+
+ int i;
+ for (i = 0; i < 5; i++) {
+ printf(" ");
+ int tmp = ticks;
+ int tmppow = pow;
+
+ while (tmppow > 0) {
+ printf("%s ", numbers[(tmp / tmppow) % 10][i]);
+ tmppow /= 10;
+ }
+ printf("\n");
+ }
+ printf("\n"
+ "*****************************************************************\n");
+
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/ck1.c b/410user/progs/ck1.c
new file mode 100644
index 0000000..c5aca41
--- /dev/null
+++ b/410user/progs/ck1.c
@@ -0,0 +1,26 @@
+/** @file 410user/progs/ck1.c
+ * @author ?
+ * @author elly1
+ * @brief Runs the checkpoint 1 script.
+ * @public yes
+ * @for p3
+ * @covers gettid
+ * @status done
+ */
+
+#include <syscall.h> /* gettid() */
+#include <simics.h> /* lprintf() */
+
+/* Main */
+int main()
+{
+ int tid;
+
+ sim_ck1();
+ tid = gettid();
+
+ lprintf("my tid is: %d", tid);
+
+ while (1)
+ continue;
+}
diff --git a/410user/progs/coolness.c b/410user/progs/coolness.c
new file mode 100644
index 0000000..b37d4a6
--- /dev/null
+++ b/410user/progs/coolness.c
@@ -0,0 +1,26 @@
+/** @file 410user/progs/coolness.c
+ * @author de0u
+ * @brief Tests fork, exec, and context-switching.
+ * @public yes
+ * @for p3
+ * @covers fork gettid exec
+ * @status done
+ */
+
+#include <syscall.h>
+#include <simics.h>
+
+char *program = "peon";
+char *args[2];
+
+int main() {
+
+ fork();
+ args[0] = program;
+ fork();
+
+ exec(program, args);
+
+ while(1)
+ lprintf("ULTIMATE BADNESS");
+}
diff --git a/410user/progs/deschedule_hang.c b/410user/progs/deschedule_hang.c
new file mode 100644
index 0000000..7f63a5e
--- /dev/null
+++ b/410user/progs/deschedule_hang.c
@@ -0,0 +1,32 @@
+/** @file 410user/progs/deschedule_hang.c
+ * @author mpa
+ * @brief Tests that deschedule() doesn't return without a corresponding
+ * make_runnable() call.
+ * @public yes
+ * @for p3
+ * @covers deschedule
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("deschedule_hang:");
+
+int main()
+{
+ int error, reject;
+ report_start(START_4EVER);
+
+ reject = 0;
+ /* stop running for quite a while */
+ error = deschedule(&reject);
+
+ report_fmt("deschedule() returned %d", error);
+
+ report_end(END_FAIL);
+ exit(1);
+}
diff --git a/410user/progs/exec_basic.c b/410user/progs/exec_basic.c
new file mode 100644
index 0000000..5cd2f6d
--- /dev/null
+++ b/410user/progs/exec_basic.c
@@ -0,0 +1,33 @@
+/** @file 410user/progs/exec_basic.c
+ * @author mpa
+ * @brief Tests basic functionality of exec()
+ * @public yes
+ * @for p3
+ * @covers exec
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <simics.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("exec_basic:");
+
+int main()
+{
+
+ REPORT_LOCAL_INIT;
+
+ char *name = "exec_basic_helper";
+ char *args[] = {name, 0};
+
+ REPORT_START_CMPLT;
+
+ REPORT_ON_ERR(exec(name,args));
+
+ REPORT_END_FAIL;
+
+ exit(-1);
+}
diff --git a/410user/progs/exec_basic_helper.c b/410user/progs/exec_basic_helper.c
new file mode 100644
index 0000000..c36b6be
--- /dev/null
+++ b/410user/progs/exec_basic_helper.c
@@ -0,0 +1,25 @@
+/** @file 410user/progs/exec_basic_helper.c
+ * @author mpa
+ * @brief Run by exec_basic to test exec.
+ * @public yes
+ * @for p3
+ * @covers nothing
+ * @status done
+ * @note Helper.
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <simics.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("exec_basic:");
+
+int main()
+{
+ REPORT_MISC("exec_basic_helper main() starting...");
+ REPORT_END_SUCCESS;
+
+ exit(1);
+}
diff --git a/410user/progs/exec_nonexist.c b/410user/progs/exec_nonexist.c
new file mode 100644
index 0000000..f2cb8dd
--- /dev/null
+++ b/410user/progs/exec_nonexist.c
@@ -0,0 +1,31 @@
+/** @file 410user/progs/exec_nonexist.c
+ * @author mpa
+ * @brief Tests exec()ing a nonexistent file.
+ * @public yes
+ * @for p3
+ * @covers exec
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("exec_nonexist:");
+
+int main() {
+ char *name = "exec_a_random_file_that_does_not_exist";
+ char *args[] = {name, 0};
+ report_start(START_CMPLT);
+
+ if (exec(name,args) >= 0) {
+ report_misc("exec() did not return an error code");
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/fib.c b/410user/progs/fib.c
new file mode 100644
index 0000000..4dc3ae9
--- /dev/null
+++ b/410user/progs/fib.c
@@ -0,0 +1,49 @@
+/** @file 410user/progs/fib.c
+ * @author acrichto
+ * @brief Computes Fibonacci series in multiple threads
+ * @public yes
+ * @for p4-smp
+ * @status done
+ */
+
+#include <410_tests.h>
+#include <stdio.h>
+#include <syscall.h>
+#include <thread.h>
+#include <thrgrp.h>
+
+DEF_TEST_NAME("fib:");
+
+#define THREADS 8
+#define FIBN 32
+
+typedef void*(thr_func)(void*);
+
+int fib(int n) {
+ if (n < 2) return n;
+ return fib(n - 1) + fib(n - 2);
+}
+
+int main() {
+ thr_init(4096);
+ int ticks = get_ticks();
+ int i, answer, guess;
+ thrgrp_group_t group;
+
+ REPORT_ON_ERR(thrgrp_init_group(&group));
+ for (i = 0; i < THREADS; i++) {
+ REPORT_ON_ERR(thrgrp_create(&group, (thr_func*) fib, (void*) FIBN));
+ }
+
+ REPORT_ON_ERR(thrgrp_join(&group, (void*) &answer));
+ for (i = 1; i < THREADS; i++) {
+ REPORT_ON_ERR(thrgrp_join(&group, (void*) &guess));
+ if (guess != answer) {
+ REPORT_END_FAIL;
+ }
+ }
+ printf("fib(%d) = %d\n", FIBN, answer);
+ printf("ticks taken: %d\n", get_ticks() - ticks);
+
+ thr_exit(0);
+}
diff --git a/410user/progs/fork_bomb.c b/410user/progs/fork_bomb.c
new file mode 100644
index 0000000..a64754f
--- /dev/null
+++ b/410user/progs/fork_bomb.c
@@ -0,0 +1,27 @@
+/** @file 410user/progs/fork_bomb.c
+ * @author zra
+ * @brief Tests fork() in low-memory conditions.
+ * @public yes
+ * @for p3
+ * @covers fork oom
+ * @status done
+ */
+
+/* Includes */
+#include <syscall.h> /* for fork */
+#include <stdlib.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("fork_bomb:");
+
+/* Main */
+int main() {
+ report_start(START_4EVER);
+ TEST_PROG_ENGAGE(200);
+
+ while (1) {
+ fork();
+ TEST_PROG_PROGRESS;
+ }
+}
diff --git a/410user/progs/fork_exit_bomb.c b/410user/progs/fork_exit_bomb.c
new file mode 100644
index 0000000..a0a8fbc
--- /dev/null
+++ b/410user/progs/fork_exit_bomb.c
@@ -0,0 +1,41 @@
+/** @file 410user/progs/fork_exit_bomb.c
+ * @author ?
+ * @brief Tests many invocations of fork/exit
+ * @public yes
+ * @for p3
+ * @covers fork set_status vanish
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("fork_exit_bomb:");
+
+int main(int argc, char *argv[]) {
+ int pid = 0;
+ int count = 0;
+
+ report_start(START_CMPLT);
+ TEST_PROG_ENGAGE(200);
+
+ lprintf("parent pid: %d", gettid());
+
+ while(count < 1000) {
+ if((pid = fork()) == 0) {
+ exit(42);
+ }
+ if(pid < 0) {
+ break;
+ }
+ count++;
+ report_fmt("child: %d", pid);
+ TEST_PROG_PROGRESS;
+ }
+
+ report_end(END_SUCCESS);
+ exit(42);
+}
diff --git a/410user/progs/fork_test1.c b/410user/progs/fork_test1.c
new file mode 100644
index 0000000..45fa9d6
--- /dev/null
+++ b/410user/progs/fork_test1.c
@@ -0,0 +1,41 @@
+/** @file 410user/progs/fork_test1.c
+ * @author zra
+ * @brief Tests basic functionality of fork()
+ * @public yes
+ * @for p3
+ * @covers fork
+ * @status done
+ */
+
+/* Includes */
+#include <syscall.h> /* for fork, getpid */
+#include <stdlib.h> /* for exit */
+#include <stdio.h> /* for lprintf */
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("fork_test1:");
+
+/* Main */
+int main(int argc, char *argv[])
+{
+ int pid;
+
+ report_start(START_CMPLT);
+ pid = fork();
+
+ if( pid < 0 ) {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ if( pid > 0 ) {
+ report_fmt("parent: tid = %d", gettid());
+ }
+ else {
+ report_fmt("child: tid = %d", gettid());
+ }
+
+ report_end(END_SUCCESS);
+ exit( 1 );
+}
diff --git a/410user/progs/fork_wait.c b/410user/progs/fork_wait.c
new file mode 100644
index 0000000..791e3e4
--- /dev/null
+++ b/410user/progs/fork_wait.c
@@ -0,0 +1,46 @@
+/** @file 410user/progs/fork_wait.c
+ * @author zra
+ * @brief Tests fork() and wait().
+ * @public yes
+ * @for p3
+ * @covers fork wait set_status vanish
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("fork_wait:");
+
+int main()
+{
+ int pid, status;
+
+ report_start(START_CMPLT);
+ pid = fork();
+
+ if (pid < 0) {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ if (pid == 0) {
+ exit(17);
+ report_end(END_FAIL); /* panic("vanish() didn't"); */
+ }
+
+ if (wait(&status) != pid) {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ if (status != 17) {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/fork_wait_bomb.c b/410user/progs/fork_wait_bomb.c
new file mode 100644
index 0000000..bb5581b
--- /dev/null
+++ b/410user/progs/fork_wait_bomb.c
@@ -0,0 +1,50 @@
+/** @file 410user/progs/fork_wait_bomb.c
+ * @author ?
+ * @brief Tests fork, wait, and exit in stress conditions.
+ * @public yes
+ * @for p3
+ * @covers fork wait set_status vanish
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("fork_wait_bomb:");
+
+int main(int argc, char *argv[]) {
+ int pid = 0;
+ int count = 0;
+ int ret_val;
+ int wpid;
+
+ report_start(START_CMPLT);
+ TEST_PROG_ENGAGE(200);
+ report_fmt("parent: %d", gettid());
+
+ while(count < 1000) {
+ if((pid = fork()) == 0) {
+ exit(42);
+ }
+ if(pid < 0) {
+ break;
+ }
+
+ count++;
+
+ report_fmt("child: %d", pid);
+ TEST_PROG_PROGRESS;
+
+ wpid = wait(&ret_val);
+
+ if(wpid != pid || ret_val != 42) {
+ report_end(END_FAIL);
+ exit(42);
+ }
+ }
+
+ report_end(END_SUCCESS);
+ exit(42);
+}
diff --git a/410user/progs/getpid_test1.c b/410user/progs/getpid_test1.c
new file mode 100644
index 0000000..5f45a3d
--- /dev/null
+++ b/410user/progs/getpid_test1.c
@@ -0,0 +1,34 @@
+/** @file 410user/progs/getpid_test1.c
+ * @author zra
+ * @brief Tests gettid().
+ * @public yes
+ * @for p2 p3
+ * @covers gettid
+ * @status done
+ */
+
+/* Includes */
+#include "410_tests.h"
+#include <report.h>
+#include <simics.h> /* for lprintf */
+#include <stdlib.h> /* for exit */
+#include <syscall.h> /* for getpid */
+
+DEF_TEST_NAME("getpid_test1:");
+
+/* Main */
+int main() {
+ int pid;
+
+ report_start(START_CMPLT);
+ pid = gettid();
+ lprintf("%s my pid is: %d", test_name, pid);
+
+ if (pid == gettid()) {
+ report_end(END_SUCCESS);
+ exit(0);
+ } else {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+}
diff --git a/410user/progs/halt_test.c b/410user/progs/halt_test.c
new file mode 100644
index 0000000..65a5b3a
--- /dev/null
+++ b/410user/progs/halt_test.c
@@ -0,0 +1,26 @@
+/** @file 410user/progs/halt_test.c
+ * @author mpa
+ * @brief Tests the basic functionality of halt()
+ * @public yes
+ * @for p2 p3
+ * @covers halt
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <simics.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("halt_test:");
+
+int main()
+{
+ REPORT_START_ABORT;
+
+ halt();
+
+ REPORT_END_FAIL;
+ exit(-1);
+}
diff --git a/410user/progs/idle.c b/410user/progs/idle.c
new file mode 100644
index 0000000..e50c6d1
--- /dev/null
+++ b/410user/progs/idle.c
@@ -0,0 +1,14 @@
+/** @file 410user/progs/idle.c
+ * @author ?
+ * @brief Idle program.
+ * @public yes
+ * @for p2 p3
+ * @covers
+ * @status done
+ */
+
+int main()
+{
+ while (1) {
+ }
+}
diff --git a/410user/progs/init.c b/410user/progs/init.c
new file mode 100644
index 0000000..f61e1a7
--- /dev/null
+++ b/410user/progs/init.c
@@ -0,0 +1,28 @@
+/** @file 410user/progs/init.c
+ * @author ?
+ * @brief Initial program.
+ * @public yes
+ * @for p2 p3
+ * @covers fork exec wait print
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+
+int main()
+{
+ int pid, exitstatus;
+ char shell[] = "shell";
+ char * args[] = {shell, 0};
+
+ while(1) {
+ pid = fork();
+ if (!pid)
+ exec(shell, args);
+
+ while (pid != wait(&exitstatus));
+
+ printf("Shell exited with status %d; starting it back up...", exitstatus);
+ }
+}
diff --git a/410user/progs/knife.c b/410user/progs/knife.c
new file mode 100644
index 0000000..f982f09
--- /dev/null
+++ b/410user/progs/knife.c
@@ -0,0 +1,43 @@
+/** @file 410user/progs/knife.c
+ * @author mpa
+ * @brief Tests fork and context-switching.
+ * @public yes
+ * @for p3
+ * @covers fork gettid
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <simics.h>
+
+#define DELAY (16*1024)
+
+int gcc_please_do_not_optimize_too_much = 0;
+
+void foo() {
+ ++gcc_please_do_not_optimize_too_much;
+}
+
+/* this function eats up a bunch of cpu cycles */
+void slow() {
+ int i;
+
+ for (i = 0; i < DELAY; i++) foo();
+}
+
+int main() {
+
+ int tid;
+
+ if ((tid = fork()) == 0)
+ while(1) {
+ slow();
+ lprintf("child: %d", gettid());
+ }
+ else
+ while(1) {
+ slow();
+ lprintf("parent: %d\t\tchild:%d", gettid(), tid);
+ }
+}
diff --git a/410user/progs/loader_test1.c b/410user/progs/loader_test1.c
new file mode 100644
index 0000000..68d389e
--- /dev/null
+++ b/410user/progs/loader_test1.c
@@ -0,0 +1,94 @@
+/** @file 410user/progs/loader_test1.c
+ * @author ?
+ * @author nwf
+ * @brief Tests loading of .data and .bss
+ * @public yes
+ * @for p3
+ * @covers exec
+ * @status done
+ */
+
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("loader_test1:");
+
+int feed = 0xfeed;
+int face = 0xface;
+char x[8192] = { 1, 2, 3 };
+int face2 = 0xface;
+void *self = (void *)&self;
+const void *cself = (void *)&cself;
+int fred;
+
+int main(int argc, char** argv) {
+
+ int *ip;
+ int ret=0;
+
+ report_start(START_CMPLT);
+
+ if (feed != 0xfeed) {
+ /* fatal */
+ report_misc(".data contains the wrong value");
+ report_end(END_FAIL);
+ ret--;
+ }
+
+ if (face != 0xface) {
+ /* fatal */
+ report_misc(".data contains the wrong value");
+ report_end(END_FAIL);
+ ret--;
+ }
+
+ ip = &feed;
+ ++ip;
+
+#ifdef notdef
+// This was not promised by the language but was essentially
+// always true... "fixed" by gcc 4.6.1-9 [gbrunsta]
+ if (*ip != 0xface) {
+ /* fatal */
+ report_misc(".data out of order... how did the previous two tests work?");
+ report_end(END_FAIL);
+ ret--;
+ }
+#endif
+
+ if (fred) {
+ /* fatal */
+ report_misc(".bss not zeroed");
+ report_end(END_FAIL);
+ ret--;
+ }
+
+ if (face2 != 0xface) {
+ /* fatal */
+ report_misc(".data contains wrong value");
+ report_end(END_FAIL);
+ ret--;
+ }
+
+ if (&feed >= &fred) {
+ /* fatal -- if even observable */
+ report_misc("linker botch???");
+ report_end(END_FAIL);
+ ret--;
+ }
+
+ if ((self != (void *)&self) || (cself != (void *)&cself)) {
+ report_misc("One of the flay-rods has gone out askew on the treadle!");
+ report_end(END_FAIL);
+ ret--;
+ }
+
+ if(ret==0)
+ {
+ report_end(END_SUCCESS);
+ return 0;
+ }
+ exit(42);
+}
diff --git a/410user/progs/loader_test2.c b/410user/progs/loader_test2.c
new file mode 100644
index 0000000..8183ae0
--- /dev/null
+++ b/410user/progs/loader_test2.c
@@ -0,0 +1,273 @@
+/** @file 410user/progs/loader_test2.c
+ * @author ?
+ * @brief Tests loading large code sections.
+ * @public yes
+ * @for p3
+ * @covers exec
+ * @status done
+ */
+
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("loader_test2:");
+
+void foo(void);
+void bar(void);
+void no44(void);
+
+extern int zipper;
+
+int main(int argc, char** argv) {
+ report_start(START_CMPLT);
+
+ foo();
+ bar();
+
+ if (zipper != 45) {
+ report_misc("FAILED: code overwriting data?");
+ no44();
+ report_end(END_FAIL);
+ exit(-1);
+ } else {
+ report_end(END_SUCCESS);
+ exit(42);
+ }
+
+}
+
+void foo(void) {
+ /* print something encouraging */
+ report_misc("first called worked");
+}
+
+void no0(void) {
+ /* fatal */
+ report_end(END_FAIL);
+}
+
+void no1(void) {
+ /* fatal */
+ no0();
+}
+
+void no2(void) {
+ /* fatal */
+ no1();
+}
+
+void no3(void) {
+ /* fatal */
+ no2();
+}
+
+void no4(void) {
+ /* fatal */
+ no3();
+}
+
+void no5(void) {
+ /* fatal */
+ no4();
+}
+
+void no6(void) {
+ /* fatal */
+ no5();
+}
+
+void no7(void) {
+ /* fatal */
+ no6();
+}
+
+void no8(void) {
+ /* fatal */
+ no7();
+}
+
+void no9(void) {
+ /* fatal */
+ no8();
+}
+
+void no10(void) {
+ /* fatal */
+ no9();
+}
+
+void no11(void) {
+ /* fatal */
+ no10();
+}
+
+void no12(void) {
+ /* fatal */
+ no11();
+}
+
+void no13(void) {
+ /* fatal */
+ no12();
+}
+
+void no14(void) {
+ /* fatal */
+ no13();
+}
+
+void no15(void) {
+ /* fatal */
+ no14();
+}
+
+void no16(void) {
+ /* fatal */
+ no15();
+}
+
+void no17(void) {
+ /* fatal */
+ no16();
+}
+
+void no18(void) {
+ /* fatal */
+ no17();
+}
+
+void no19(void) {
+ /* fatal */
+ no18();
+}
+
+void no20(void) {
+ /* fatal */
+ no19();
+}
+void no21(void) {
+ /* fatal */
+ no20();
+}
+
+void no22(void) {
+ /* fatal */
+ no21();
+}
+
+void no23(void) {
+ /* fatal */
+ no22();
+}
+
+void no24(void) {
+ /* fatal */
+ no23();
+}
+
+void no25(void) {
+ /* fatal */
+ no24();
+}
+
+void no26(void) {
+ /* fatal */
+ no25();
+}
+
+void no27(void) {
+ /* fatal */
+ no26();
+}
+
+void no28(void) {
+ /* fatal */
+ no27();
+}
+void no29(void) {
+ /* fatal */
+ no28();
+}
+
+void no30(void) {
+ /* fatal */
+ no29();
+}
+
+void no31(void) {
+ /* fatal */
+ no30();
+}
+
+void no32(void) {
+ /* fatal */
+ no31();
+}
+
+void no33(void) {
+ /* fatal */
+ no32();
+}
+
+void no34(void) {
+ /* fatal */
+ no33();
+}
+
+void no35(void) {
+ /* fatal */
+ no34();
+}
+
+void no36(void) {
+ /* fatal */
+ no35();
+}
+
+void no37(void) {
+ /* fatal */
+ no36();
+}
+
+void no38(void) {
+ /* fatal */
+ no37();
+}
+
+void no39(void) {
+ /* fatal */
+ no38();
+}
+
+void no40(void) {
+ /* fatal */
+ no39();
+}
+
+void no41(void) {
+ /* fatal */
+ no40();
+}
+
+void no42(void) {
+ /* fatal */
+ no41();
+}
+
+void no43(void) {
+ /* fatal */
+ no42();
+}
+
+void no44(void) {
+ /* fatal */
+ no43();
+}
+
+void bar(void) {
+ report_misc("second call worked");
+}
+
+int zipper=45;
diff --git a/410user/progs/make_crash.c b/410user/progs/make_crash.c
new file mode 100644
index 0000000..7cece01
--- /dev/null
+++ b/410user/progs/make_crash.c
@@ -0,0 +1,50 @@
+/** @file 410user/progs/make_crash.c
+ * @author rsa
+ * @author kcaffrey
+ * @brief Forkbombs, sleeps for a while, then exec()s a helper
+ * @public yes
+ * @for p3
+ * @covers fork, exec, wait
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME ("make_crash:");
+
+int main(int argc, char **argv) {
+ int i, tid, status;
+ int parentTID = gettid ();
+ char *name = "make_crash_helper";
+ char s_parentTID[11];
+ sprintf(s_parentTID, "%d", parentTID);
+ char *argvec[] = {name, "evil test", s_parentTID, 0};
+ char buf[100];
+ REPORT_START_CMPLT;
+
+ REPORT_MISC("This test brought to you by Group 35 (Fall 03) - rsa & kcaffrey\n");
+ REPORT_MISC("Starting forks");
+
+ for(i=0; i<7; i++) {
+ if ((tid=fork())==0) {
+ sprintf(buf, " Starting sleep I am %d", gettid());
+ REPORT_MISC(buf);
+ sleep(100);
+ }
+ }
+
+ sprintf(buf, " Done with my forks, I am %d", gettid());
+ REPORT_MISC(buf);
+
+ while ((tid=wait(&status))>=0) {
+ sprintf(buf, " Reaped child %d with status %d, I am %d", tid, status, gettid());
+ REPORT_MISC(buf);
+ }
+
+ sleep(200);
+ exec(name, argvec);
+
+ return -40;
+}
diff --git a/410user/progs/make_crash_helper.c b/410user/progs/make_crash_helper.c
new file mode 100644
index 0000000..a5aa63e
--- /dev/null
+++ b/410user/progs/make_crash_helper.c
@@ -0,0 +1,41 @@
+/** @file 410user/progs/make_crash_helper.c
+ * @author rza
+ * @author kcaffrey
+ * @brief Helper for make_crash. Forks and checks its tid.
+ * @public yes
+ * @for p3
+ * @covers gettid fork
+ * @status done
+ * @note Helper.
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("make_crash:");
+
+int main(int argc, char **argv) {
+ if (argc < 3) {
+ return -50;
+ }
+ char buf[200];
+ sprintf(buf, " My program is %s, my argument is %s and %s TID=%d", argv[0], argv[1], argv[2], gettid());
+ REPORT_MISC(buf);
+
+ if (fork()==0)
+ return 0;
+
+ REPORT_MISC(" I am an exec-ed parent");
+
+ /* Should print when parent execs and exits */
+ if (gettid() == atoi(argv[2])) {
+ REPORT_END_SUCCESS;
+ return 10000;
+ }
+
+ return gettid();
+}
diff --git a/410user/progs/mem_eat_test.c b/410user/progs/mem_eat_test.c
new file mode 100644
index 0000000..7e29275
--- /dev/null
+++ b/410user/progs/mem_eat_test.c
@@ -0,0 +1,58 @@
+/** @file 410user/progs/mem_eat_test.c
+ * @author ?
+ * @brief Grows the stack until it dies.
+ * @public yes
+ * @for p3
+ * @covers oom autostack
+ * @status done
+ */
+
+#include <limits.h>
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("mem_eat_test:");
+
+#define MEGABYTE (1024*1024)
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+void touch_array(char *p);
+void foo(int index);
+
+int main(int argc, char *argv[]) {
+ report_start(START_ABORT);
+ foo(1);
+ report_end(END_FAIL);
+ return 42;
+}
+
+/* touch one byte per page to run faster.
+ * this code is a separate function so gcc doesn't optimize
+ * away the array writing.
+ */
+void touch_array(char *p) {
+ int i;
+ for(i = MEGABYTE - 1; i >= 0; i -= PAGE_SIZE) {
+ p[i] = 'a';
+ }
+}
+
+void foo(int index)
+{
+ char local_array[MEGABYTE];
+
+ if (index == INT_MAX)
+ // We will never get here. But the notion that we might get
+ // here defeats clang's clever infinite-recursion detector.
+ return;
+
+ touch_array(local_array);
+
+ report_fmt("used %d pages = %d MB", index * (MEGABYTE / PAGE_SIZE), index);
+ foo(index + 1);
+}
diff --git a/410user/progs/mem_permissions.c b/410user/progs/mem_permissions.c
new file mode 100644
index 0000000..eb6cc46
--- /dev/null
+++ b/410user/progs/mem_permissions.c
@@ -0,0 +1,98 @@
+/** @file 410user/progs/mem_permissions.c
+ * @author mpa
+ * @brief Tests memory permissions.
+ * @public yes
+ * @for p3
+ * @covers vm
+ * @status done
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("mem_permissions:");
+
+/* forks off a task to die writing to the address */
+void attempt_write(int *addr)
+{
+ int pid, pid2, status = 333;
+ REPORT_LOCAL_INIT;
+
+ REPORT_FAILOUT_ON_ERR((pid = fork()));
+
+ if (pid == 0) {
+ *addr = 42;
+
+ REPORT_END_FAIL;
+ exit(42);
+ }
+
+ REPORT_FAILOUT_ON_ERR((pid2 = wait(&status)));
+
+ if (pid != pid2) {
+ report_fmt("Bad pid %d (should be %d)", pid2, pid);
+ REPORT_END_FAIL;
+ exit(42);
+ }
+ if (status >= 0) {
+ report_fmt("Bad status %d", status);
+ REPORT_END_FAIL;
+ exit(42);
+ }
+ report_fmt("Good: attempt_write(0x%x)", addr);
+}
+
+/* forks off a task to die reading from the address */
+void attempt_read(int *addr)
+{
+ int pid, pid2, status = 444;
+ REPORT_LOCAL_INIT;
+
+ REPORT_FAILOUT_ON_ERR((pid = fork()));
+
+ if (pid == 0) {
+ pid = *addr;
+
+ REPORT_END_FAIL;
+ exit(pid);
+ }
+
+ REPORT_FAILOUT_ON_ERR((pid2 = wait(&status)));
+
+ if (pid != pid2) {
+ report_fmt("Bad pid %d (should be %d)", pid2, pid);
+ REPORT_END_FAIL;
+ exit(42);
+ }
+ if (status >= 0) {
+ report_fmt("Bad status %d", status);
+ REPORT_END_FAIL;
+ exit(42);
+ }
+ report_fmt("Good: attempt_read(0x%x)", addr);
+}
+
+const char header[4096] = "push rodata onto its own page";
+const char array[] = "constant";
+const char trailer[4096] = "push other things off of rodata page";
+
+int main()
+{
+ REPORT_START_CMPLT;
+
+ /* try reading/writing kernel memory */
+ attempt_read((int *)0x500000);
+ attempt_write((int *)0x500000);
+
+ /* try writing rodata section */
+ attempt_write((int *)array);
+
+ /* try writing text secion */
+ attempt_write((int *)main);
+
+ REPORT_END_SUCCESS;
+
+ exit(0);
+}
diff --git a/410user/progs/merchant.c b/410user/progs/merchant.c
new file mode 100644
index 0000000..daa5713
--- /dev/null
+++ b/410user/progs/merchant.c
@@ -0,0 +1,59 @@
+/** @file 410user/progs/merchant.c
+ * @author mpa
+ * @brief Tests basic functionality of exec()
+ * @public yes
+ * @for p3
+ * @covers exec
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <string.h>
+#include <simics.h>
+
+#define DELAY (16*1024)
+
+int gcc_please_do_not_optimize_too_much = 0;
+
+void foo() {
+ ++gcc_please_do_not_optimize_too_much;
+}
+
+/* this function eats up a bunch of cpu cycles */
+void slow() {
+ int i;
+
+ for (i = 0; i < DELAY; i++) foo();
+}
+
+int main(int argc, char **argv) {
+
+ int tid = gettid();
+
+ char buf[16];
+ char msg[128];
+
+ sprintf(buf, "%d", tid);
+
+ /* select a message to print out */
+ if (argc != 4)
+ sprintf(msg,
+ "WARNING: incorrect number of arguments - got %d, expected %d",
+ argc,
+ 4);
+ else if (strcmp("merchant", argv[0]) != 0 ||
+ strcmp("13", argv[1]) != 0 ||
+ strcmp("foo bar", argv[2]) != 0)
+ sprintf(msg, "WARNING: incorrect arguments");
+ else if (strcmp(argv[3], buf))
+ sprintf(msg, "WARNING: tid changed");
+ else
+ sprintf(msg, "Hello!");
+
+ /* print message forever */
+ while(1) {
+ slow();
+ lprintf("Message from merchant #%d:\t%s", tid, msg);
+ }
+}
diff --git a/410user/progs/minclone_many.S b/410user/progs/minclone_many.S
new file mode 100644
index 0000000..27c4546
--- /dev/null
+++ b/410user/progs/minclone_many.S
@@ -0,0 +1,177 @@
+/**
+ * @file minclone_many.S
+ * @author nwf
+ * @author de0u
+ * @brief Spawn many threads within a task:
+ * 128 blocks of 64 threads, with
+ * occasional pauses for cleanup.
+ * @public yes
+ * @for p3
+ */
+
+#include "410_tests.h"
+#include <syscall_int.h>
+
+.section .rodata
+
+test_name:
+ .string "minclone_many:"
+str3str:
+ .string "%s%s%s"
+str_thread:
+ .string "%s: hello from tid %d in block %d"
+test_start:
+ .string TEST_START_CMPLT
+test_error:
+ .string TEST_END_FAIL
+test_finish:
+ .string TEST_END_SUCCESS
+test_pfx:
+ .string TEST_PFX
+
+line_fmt:
+ .string "%02X "
+
+str_T:
+ .string "T"
+str_bang:
+ .string "!"
+str_newline:
+ .string "\n"
+.align 4
+/* syscall packets for print() */
+print_T_args:
+ .long 1
+ .long str_T
+print_bang_args:
+ .long 1
+ .long str_bang
+print_newline_args:
+ .long 1
+ .long str_newline
+
+.section .text
+
+/* Created threads avoid using the original thread's stack.
+ * XXX Arguably better: array hosting thread stacks.
+ */
+
+.global main
+main:
+ pushl %ebp
+ movl %esp,%ebp
+
+ /* REPORT_START_CMPLT */
+ pushl $test_start
+ pushl $test_name
+ pushl $test_pfx
+ pushl $str3str
+ call lprintf
+ movl %ebp,%esp
+
+ /* set_status(-17) */
+ movl $-17,%esi
+ int $SET_STATUS_INT
+
+ /* Engage grading-harness progress sensor */
+ /* sim_fr_prog(30) */
+ movl $30, %ecx
+ movl $SIM_FR_PROG, %ebx
+ xchg %bx, %bx
+
+ movl $128, %edx /* %edx = block count */
+
+block_loop:
+ /* printf("%02x ", block) */
+ pushl %ecx
+ pushl %edx
+ pushl $line_fmt
+ call printf
+ popl %eax
+ popl %edx
+ popl %ecx
+
+ movl $64, %ecx /* %ecx = per-block thread count */
+
+thread_loop:
+ int $THREAD_FORK_INT
+ cmpl $0x0, %eax
+ jg parent_thread
+ jl error
+
+spawned_thread:
+ /* Declare progress to grading harness */
+ /* sim_fr_here() */
+ movl $SIM_FR_HERE, %ebx
+ xchg %bx, %bx
+
+ /* print(1, "T") */
+ movl $print_T_args, %esi
+ int $PRINT_INT
+
+ int $VANISH_INT
+
+parent_thread:
+ decl %ecx
+ jne thread_loop
+
+ /* sleep(7) -- hopefully enough for the threads to finish */
+ movl $7,%esi
+ int $SLEEP_INT
+
+ /* print(1, "\n") */
+ movl $print_newline_args, %esi
+ int $PRINT_INT
+
+ decl %edx
+ jne block_loop
+
+finish:
+ /* REPORT_END_SUCCESS */
+ pushl $test_finish
+ pushl $test_name
+ pushl $test_pfx
+ pushl $str3str
+ call lprintf
+ movl %ebp,%esp
+ pushl $1
+ pushl $test_name
+ call sim_update_scoreboard
+ movl %ebp,%esp
+
+ /* set_status(0) */
+ movl $0x0,%esi
+ int $SET_STATUS_INT
+
+ int $VANISH_INT
+
+error:
+ /* print(1, "!") */
+ movl $print_bang_args, %esi
+ int $PRINT_INT
+
+ /* sleep(7) -- hopefully drain out broken partial block of threads */
+ movl $7,%esi
+ int $SLEEP_INT
+
+ /* print(1, "\n") */
+ movl $print_newline_args, %esi
+ int $PRINT_INT
+
+ /* REPORT_END_FAIL */
+ pushl $test_error
+ pushl $test_name
+ pushl $test_pfx
+ pushl $str3str
+ call lprintf
+ call printf
+ movl $print_newline_args, %esi
+ int $PRINT_INT
+ movl %ebp,%esp
+ pushl $0
+ pushl $test_name
+ call sim_update_scoreboard
+ movl %ebp,%esp
+
+ int $VANISH_INT
+
diff --git a/410user/progs/minclone_mem.S b/410user/progs/minclone_mem.S
new file mode 100644
index 0000000..0cef2f5
--- /dev/null
+++ b/410user/progs/minclone_mem.S
@@ -0,0 +1,78 @@
+/** @file 410user/progs/minclone_mem.S
+ * @author mpa
+ * @brief Tests sharing of memory in thread_fork
+ * @public yes
+ * @for p3
+ * @covers thread_fork
+ * @status needswork
+ */
+
+#include "410_tests.h"
+#include "syscall_int.h"
+
+.global main
+
+test_name:
+ .string "minclone_mem:"
+str:
+ .string "%s%s%s"
+test_start:
+ .string TEST_START_CMPLT
+test_pfx:
+ .string TEST_PFX
+test_end_success:
+ .string TEST_END_SUCCESS
+
+
+.comm hpvar,4,4
+
+main:
+ pushl %ebp
+ movl %esp,%ebp
+
+ pushl $test_start
+ pushl $test_name
+ pushl $test_pfx
+ pushl $str
+ call lprintf
+
+ movl $0x0,hpvar
+ addl $0x4,%esp
+ movl $0x0,4(%esp)
+
+ /* fork a thread */
+ int $THREAD_FORK_INT
+
+ cmpl $0x0,%eax
+ je child
+
+parent:
+ movl $0x172,4(%esp) /* signal child */
+loop:
+ cmpl $0xbacacaba,hpvar /* wait to be signaled */
+ jne loop
+
+ /* Ok, test was successful... */
+
+ pushl $test_end_success
+ pushl $test_name
+ pushl $test_pfx
+ pushl $str
+ call lprintf
+
+ /* exit(0) */
+ movl $0x0,%esi
+ int $SET_STATUS_INT
+ int $VANISH_INT
+
+ leave
+ ret
+
+
+child:
+ cmpl $0x172,4(%esp) /* wait to be signaled */
+ jne child
+
+ movl $0xbacacaba,hpvar /* signal parent */
+
+ int $VANISH_INT /* bye-bye */
diff --git a/410user/progs/new_pages.c b/410user/progs/new_pages.c
new file mode 100644
index 0000000..749c02b
--- /dev/null
+++ b/410user/progs/new_pages.c
@@ -0,0 +1,95 @@
+/** @file 410user/progs/new_pages.c
+ * @author de0u
+ * @brief Tests new_pages() a lot.
+ * @public yes
+ * @for p3
+ * @covers new_pages
+ * @status done
+ */
+
+/* Here's what we do */
+int new_stack(void); /* new_pages() into the stack */
+int new_data(void); /* new_pages() into data region */
+int lotsa_luck(void); /* new_pages() "too much" memory */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "410_tests.h"
+#include <report.h>
+#include <test.h>
+
+/* Yes, I mean this--see below */
+#define TEST_NAME "new_pages:"
+DEF_TEST_NAME(TEST_NAME);
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+#define PAGE_BASE(a) (((int)(a)) & ~(PAGE_SIZE - 1))
+
+int main(int argc, char *argv[]) {
+ int rets[3], i;
+ char mbuf[256];
+
+ REPORT_START_CMPLT;
+
+ rets[0] = new_stack();
+ rets[1] = new_data();
+ rets[2] = lotsa_luck();
+
+ for (i = 0; i < sizeof (rets) / sizeof (rets[0]); ++i) {
+ if (rets[i] == 0) {
+ REPORT_MISC("I *want* my outs to count!!!"); /* Christine Lavin */
+ report_fmt("died on %d", i);
+ REPORT_END_FAIL;
+ exit(71);
+ }
+ }
+
+ format_end(mbuf, sizeof(mbuf), END_SUCCESS);
+
+ exhaustion(exit_success, mbuf);
+
+ REPORT_END_SUCCESS;
+ exit(0);
+}
+
+int
+new_stack(void)
+{
+ int answer = 42;
+ int ret;
+
+ ret = new_pages((void *)PAGE_BASE((&answer)), PAGE_SIZE);
+ if (answer != 42) {
+ REPORT_MISC("My brain hurts!"); /* T.F. Gumby */
+ REPORT_END_FAIL;
+ exit(71);
+ }
+ return (ret);
+}
+
+int
+new_data(void)
+{
+ int ret;
+
+ ret = new_pages((void *)PAGE_BASE(test_name), PAGE_SIZE);
+ if (strcmp(test_name, TEST_NAME)) {
+ report_misc("new_pages() killed .data?");
+ REPORT_END_FAIL;
+ exit(71);
+ }
+ return (ret);
+}
+
+#define ADDR 0x40000000
+#define GIGABYTE (1024*1024*1024)
+
+int
+lotsa_luck(void)
+{
+ return (new_pages((void *)ADDR, GIGABYTE));
+}
diff --git a/410user/progs/new_shell.c b/410user/progs/new_shell.c
new file mode 100644
index 0000000..e3a0135
--- /dev/null
+++ b/410user/progs/new_shell.c
@@ -0,0 +1,27 @@
+/** @file new_shell.c
+ * @brief This program tests the new_console() syscall by spawning a
+ * new shell
+ *
+ * @author Geoffrey G. Wilson (ggw)
+ * @author E. Chaos Golubitsky (egolubit)
+ *
+ */
+#include <syscall.h>
+#include <stdio.h>
+
+int main()
+{
+ char *argvec[] = { "shell", 0} ;
+
+ if (!(fork())) {
+ printf("i am thread %d; about to switch consoles\n", gettid());
+ if (new_console() < 0) {
+ printf("failed to create new console\n");
+ return(-1);
+ } else {
+ exec(argvec[0], argvec);
+ }
+ }
+
+ return(0);
+}
diff --git a/410user/progs/peon.c b/410user/progs/peon.c
new file mode 100644
index 0000000..2a37bb5
--- /dev/null
+++ b/410user/progs/peon.c
@@ -0,0 +1,35 @@
+/** @file 410user/progs/peon.c
+ * @author mpa
+ * @brief Tests exec() by launching merchant.
+ * @public yes
+ * @for p3
+ * @covers exec
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <simics.h>
+
+int main() {
+
+ int tid = gettid();
+
+ char buf[16];
+ char * prog = "merchant";
+ char * args[5] = { "merchant", "13", "foo bar", NULL, NULL };
+
+ args[3] = buf;
+ sprintf(buf, "%d", tid);
+
+ lprintf("promoting peon #%d to a merchant", tid);
+
+ if (exec(prog, args) < 0)
+ lprintf("ABORTING: exec returned error");
+ else
+ lprintf("ABORTING: exec returned success");
+
+ /* infinite loop as exit may not be implemented */
+ while(1);
+}
diff --git a/410user/progs/print_basic.c b/410user/progs/print_basic.c
new file mode 100644
index 0000000..37c3c2b
--- /dev/null
+++ b/410user/progs/print_basic.c
@@ -0,0 +1,27 @@
+/** @file 410user/progs/print_basic.c
+ * @author mpa
+ * @author mtomczak
+ * @brief Tests print().
+ * @public yes
+ * @for p3
+ * @covers print
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("print_basic:");
+
+int main()
+{
+ REPORT_START_CMPLT;
+ if (print(13, "Hello World!\n") != 0)
+ REPORT_END_FAIL;
+ else
+ REPORT_END_SUCCESS;
+
+ exit(0);
+}
diff --git a/410user/progs/progs.mk b/410user/progs/progs.mk
new file mode 100644
index 0000000..4dc9b89
--- /dev/null
+++ b/410user/progs/progs.mk
@@ -0,0 +1,15 @@
+410UPROGS = $(patsubst %,$(410UDIR)/$(UPROGDIR)/%,$(410REQPROGS) $(410TESTS))
+STUUPROGS = $(patsubst %,$(STUUDIR)/$(UPROGDIR)/%,$(STUDENTREQPROGS) $(STUDENTTESTS))
+410UBINPROGS = $(patsubst %,$(410UDIR)/$(UPROGDIR)/%,$(410REQBINPROGS))
+
+410UCLEANS += $(410UPROGS) $(410UBINPROGS)
+
+$(410UBINPROGS): %: %.bin
+ cp $< $@
+
+ULIBS=$(410ULIBS_EARLY) $(STUULIBS_EARLY) $(410ULIBS_LATE) $(STUULIBS_LATE)
+$(410UPROGS) $(EXTRA_410_PROGS): %: %.o $(CRT0) $(ULIBS)
+ $(LD) $(LDFLAGS) -o $@ $< $(CRT0) --start-group $(ULIBS) --end-group
+
+$(STUUPROGS): %: %.o $(CRT0) $(ULIBS)
+ $(LD) $(LDFLAGS) -o $@ $< $(CRT0) --start-group $(ULIBS) --end-group
diff --git a/410user/progs/readline_basic.c b/410user/progs/readline_basic.c
new file mode 100644
index 0000000..b60ebfe
--- /dev/null
+++ b/410user/progs/readline_basic.c
@@ -0,0 +1,25 @@
+/** @file 410user/progs/readline_basic.c
+ * @author mpa
+ * @brief Tests readline()
+ * @public yes
+ * @for p3
+ * @covers readline
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <simics.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("readline_basic:");
+
+int main() {
+ char buf[100];
+ report_start(START_CMPLT);
+ REPORT_FAILOUT_ON_ERR(magic_readline(100, buf));
+ report_misc(buf);
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/register_test.S b/410user/progs/register_test.S
new file mode 100644
index 0000000..a45f866
--- /dev/null
+++ b/410user/progs/register_test.S
@@ -0,0 +1,172 @@
+/** @file 410user/progs/register_test.S
+ * @author mpa
+ * @author ctokar
+ * @brief Tests that registers are saved over context switches.
+ * @public yes
+ * @for p3
+ * @covers ctxsw
+ * @status needswork
+ */
+
+#include "410_tests.h"
+
+.global main
+ .section .rodata
+
+test_name:
+ .string "register_test:"
+str:
+ .string "%s%s%s"
+test_start:
+ .string TEST_START_4EVER
+test_pfx:
+ .string TEST_PFX
+test_end_fail:
+ .string TEST_END_FAIL
+
+.align 4
+eax:
+
+ .long 0x17
+ebx:
+ .long 0x42
+ecx:
+ .long 0xffffffff
+edx:
+ .long 0xc001d00d
+esi:
+ .long 0x9999abcd
+edi:
+ .long 0x12345678
+ebp:
+ .long 0x87654321
+esp:
+ .long 0xbaaaaaaa
+eax2:
+ .long 0x20
+ebx2:
+ .long 0x45
+ecx2:
+ .long 0x01010101
+edx2:
+ .long 0xbeef0011
+esi2:
+ .long 0xfeedcafe
+edi2:
+ .long 0x98765432
+ebp2:
+ .long 0x12457802
+esp2:
+ .long 0xabcdefab
+str2:
+ .string "%s%sOoops: %%eax=0x%x, %%ebx=0x%x, %%ecx=0x%x, %%edx=0x%x, %%esi=0x%x, %%edi=0x%x, %%esp=0x%x, %%ebp=0x%x\n"
+ .text
+.comm oldesp,4,4
+.comm oldebp,4,4
+.comm newesp,4,4
+.comm newebp,4,4
+
+main:
+ movl %esp,oldesp
+ movl %ebp,oldebp
+
+ movl %esp,%ebp
+ pushl $test_start
+ pushl $test_name
+ pushl $test_pfx
+ pushl $str
+ call lprintf
+
+ call fork
+ cmp $0, %eax
+ je child
+
+parent:
+.align 8
+ movl eax,%eax
+ movl ebx,%ebx
+ movl ecx,%ecx
+ movl edx,%edx
+ movl esi,%esi
+ movl edi,%edi
+ movl ebp,%ebp
+ movl esp,%esp
+
+loop:
+ cmpl eax,%eax
+ jne oops
+ cmpl ebx,%ebx
+ jne oops
+ cmpl ecx,%ecx
+ jne oops
+ cmpl edx,%edx
+ jne oops
+ cmpl esi,%esi
+ jne oops
+ cmpl edi,%edi
+ jne oops
+ cmpl ebp,%ebp
+ jne oops
+ cmpl esp,%esp
+ jne oops
+ jmp loop
+
+child:
+.align 8
+ movl eax2,%eax
+ movl ebx2,%ebx
+ movl ecx2,%ecx
+ movl edx2,%edx
+ movl esi2,%esi
+ movl edi2,%edi
+ movl ebp2,%ebp
+ movl esp2,%esp
+
+loop2:
+ cmpl eax2,%eax
+ jne oops
+ cmpl ebx2,%ebx
+ jne oops
+ cmpl ecx2,%ecx
+ jne oops
+ cmpl edx2,%edx
+ jne oops
+ cmpl esi2,%esi
+ jne oops
+ cmpl edi2,%edi
+ jne oops
+ cmpl ebp2,%ebp
+ jne oops
+ cmpl esp2,%esp
+ jne oops
+ jmp loop2
+
+oops:
+ movl %esp,newesp
+ movl oldesp,%esp
+ movl %ebp,newebp
+ movl oldesp,%ebp
+
+ push newebp
+ push newesp
+ push $edi
+ push $esi
+ push $edx
+ push $ecx
+ push $ebx
+ push $eax
+ push $test_name
+ push $test_pfx
+ push $str2
+ call lprintf
+
+ push $test_end_fail
+ push $test_name
+ push $test_pfx
+ push $str
+ call lprintf
+
+ movl oldesp,%esp
+ movl oldebp,%ebp
+ movl $0xffffffff,%eax
+ ret
diff --git a/410user/progs/remove_pages_test1.c b/410user/progs/remove_pages_test1.c
new file mode 100644
index 0000000..6c751ba
--- /dev/null
+++ b/410user/progs/remove_pages_test1.c
@@ -0,0 +1,63 @@
+/** @file 410user/progs/remove_pages_test1.c
+ * @author mpa
+ * @brief Tests remove_pages()
+ * @public yes
+ * @for p3
+ * @covers remove_pages new_pages
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+#define ADDR 0x40000000
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+DEF_TEST_NAME("remove_pages_test1:");
+
+int main() {
+ int i;
+ int size;
+ int failed = 0;
+
+ report_start(START_CMPLT);
+ lprintf("This test exercises remove_pages\n");
+ lprintf("It assumes that new_pages works as spec\n");
+
+ for(size = 1; size < 50; size++) {
+ /* allocate pages */
+ if (new_pages((void *)ADDR, size * PAGE_SIZE) != 0) {
+ lprintf("new_pages failed to allocated %d bytes at %x",
+ size * PAGE_SIZE, ADDR);
+ failed = 1;
+ }
+
+ /* verify pages */
+ for (i = 0; i < size; i++) {
+ if (*(int *)(ADDR + i * PAGE_SIZE) != 0) {
+ lprintf("allocated page not zeroed at %x", ADDR + i * PAGE_SIZE);
+ failed = 1;
+ }
+ *(int *)(ADDR + i * PAGE_SIZE) = i+1;
+ }
+
+ /* remove pages */
+ if (remove_pages((void *)ADDR) != 0) {
+ lprintf("remove_pages failed to remove pages at %x", ADDR);
+ failed = 1;
+ }
+
+ }
+
+ if (failed) {
+ report_end(END_FAIL);
+ return -1;
+ }
+
+ report_end(END_SUCCESS);
+ return 0;
+}
diff --git a/410user/progs/remove_pages_test2.c b/410user/progs/remove_pages_test2.c
new file mode 100644
index 0000000..d79bf2b
--- /dev/null
+++ b/410user/progs/remove_pages_test2.c
@@ -0,0 +1,60 @@
+/** @file 410user/progs/remove_pages_test2.c
+ * @author mpa
+ * @brief Tests remove_pages()
+ * @public yes
+ * @for p3
+ * @covers new_pages remove_pages
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+#define ADDR 0x40000000
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+DEF_TEST_NAME("remove_pages_test2:");
+
+int main() {
+ report_start(START_ABORT);
+ lprintf("This test checks that remove_pages removed the pages\n");
+ lprintf("It assumes that new_pages works as spec\n");
+
+ /* allocate a couple pages */
+ if (new_pages((void *)ADDR, 5 * PAGE_SIZE) != 0) {
+ lprintf("new_pages failed at %x", ADDR);
+ report_end(END_FAIL);
+ return -1;
+ }
+
+ if (*(int *)(ADDR + 2 * PAGE_SIZE) != 0) {
+ lprintf("allocated page not zeroed at %x", ADDR + 2 * PAGE_SIZE);
+ report_end(END_FAIL);
+ return -1;
+ }
+ *(int *)(ADDR + 2 * PAGE_SIZE) = 5;
+
+ if (remove_pages((void *)ADDR) != 0) {
+ lprintf("remove_pages failed to remove pages at %x", ADDR);
+ report_end(END_FAIL);
+ return -1;
+ }
+
+ report_misc("pages removed");
+
+ switch (*(int *)(ADDR + 2 * PAGE_SIZE)) {
+ case 5:
+ report_misc("pages not really removed");
+ break;
+
+ default:
+ report_fmt("pages still mapped, got %d", *(int *)(ADDR + 2 * PAGE_SIZE));
+ break;
+ }
+ report_end(END_FAIL);
+ return -1;
+}
diff --git a/410user/progs/score.c b/410user/progs/score.c
new file mode 100644
index 0000000..29ed81a
--- /dev/null
+++ b/410user/progs/score.c
@@ -0,0 +1,146 @@
+/** @file 410user/progs/score.c
+ *
+ * @author Ryan Chen (ryanc1)
+ * @author Urvi Agrawal (urvia)
+ *
+ * @brief Runs batches of scoreboard tests based on flags provided in argv
+ * @public yes
+ * @for p3
+ * @covers argc/argv, fork(), exec(), new_pages(), remove_pages()
+ *
+ * @bug None known
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "syscall.h"
+#include "simics.h"
+#include "string.h"
+
+// These tests will be run if no other test suite is specified in argv.
+// @covers Loading, getpid(), exec(), fork(), print()
+char *default_tests[] = {
+ "getpid_test1",
+ "loader_test1",
+ "loader_test2",
+ "exec_basic",
+ "exec_nonexist",
+ "fork_test1",
+ "print_basic",
+ NULL,
+};
+
+// Run these tests by adding "memory" to argv.
+// @covers new_pages(), remove_pages(), page fault handler,
+// zeroed allocations/ZFOD
+char *memory_tests[] = {
+ "new_pages",
+ "remove_pages_test1",
+ "mem_permissions",
+ NULL,
+};
+
+typedef struct {
+ char *name;
+ char **programs;
+} TestSuite;
+
+// Array mapping strings potentially in argv[1] to test tables
+TestSuite suites[] = {
+ {"memory", memory_tests},
+ {NULL, default_tests},
+};
+
+// You know how in kindergarten you didn't actually sleep during
+// naptime so you just counted the number of tiles on the ceiling?
+// No? Just me?
+#define FAKE_SLEEP_DELAY 8096
+int num_tiles_gcc_please_I_want_to_live = 0;
+
+static void spin_delay() {
+ for (int i = 0; i < FAKE_SLEEP_DELAY; i++) {
+ ++num_tiles_gcc_please_I_want_to_live;
+ }
+}
+
+// Returns 0 if x == NULL, y == NULL
+// Returns some unspecified non-zero value if only one of x or y is NULL
+// Otherwise, returns strcmp(x, y)
+int safe_strcmp(char *x, char *y) {
+ if (x == NULL && y == NULL) {
+ return 0;
+ } else if (x == NULL) {
+ return -42;
+ } else if (y == NULL) {
+ return -42;
+ } else {
+ return strcmp(x, y);
+ }
+}
+
+// Mass fork()/exec() all the tests in the named test suite.
+void fork_test_suite(TestSuite *test_suite) {
+ if (test_suite->name == NULL) {
+ lprintf("score: Running default test suite.");
+ } else {
+ lprintf("score: Running test suite '%s'", test_suite->name);
+ }
+
+ int program_num = 0;
+ while (test_suite->programs[program_num] != NULL) {
+ int pid = fork();
+ char *testname = test_suite->programs[program_num];
+
+ if (pid < 0) {
+ lprintf("score: fork() failed while launching %s", testname);
+ spin_delay();
+ } else if (pid == 0) {
+ char *args[2];
+ args[0] = testname;
+ args[1] = NULL;
+
+ exec(testname, args);
+
+ lprintf("score: exec(%s) failed..?", testname);
+ } else { // pid > 0
+ ++program_num;
+ }
+ }
+}
+
+void run_suite(char *suite_name) {
+ int num_suites_loaded = sizeof(suites) / sizeof(suites[0]);
+ for (int i = 0; i < num_suites_loaded; i++) {
+ if (safe_strcmp(suite_name, suites[i].name) == 0) {
+ fork_test_suite(&suites[i]);
+ return;
+ }
+ }
+
+ lprintf("score: test suite '%s' not found.", suite_name);
+}
+
+
+int main(int argc, char **argv) {
+ if (argc == 0) { // Maybe argv is not correct?
+ lprintf("score: argc == 0??");
+ } else {
+ run_suite(NULL); // Always run the default suite.
+ if (argc >= 2) {
+ run_suite(argv[1]); // Additionally, run a named test suite
+ }
+ }
+
+ // Since this test is meant to be run instead of init (before the shell is
+ // functional), this program must be persistent.
+ int sheep = 0;
+ while (true) {
+ ++sheep;
+ spin_delay();
+ }
+
+ lprintf("score: escaped infinite loop???");
+ return -42; // Hopefully not.
+}
diff --git a/410user/progs/shell.c b/410user/progs/shell.c
new file mode 100644
index 0000000..5546d7f
--- /dev/null
+++ b/410user/progs/shell.c
@@ -0,0 +1,276 @@
+/** @file 410user/progs/shell.c
+ * @author ?
+ * @brief The shell.
+ * @public yes
+ * @for p2 p3
+ * @covers fork exec wait set_status vanish print ls
+ * @status done
+ */
+
+/* --- Since we're not calling thr_init() --- */
+/* (this is sleazy violence, *not* good form) */
+#define malloc _malloc
+#define calloc _calloc
+#define realloc _realloc
+#define free _free
+
+/* --- Includes --- */
+#include <string.h>
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <simics.h>
+
+/* --- Defines --- */
+#define MAX_LENGTH 1024
+
+
+/* --- Initialized Global Strings --- */
+char prompt[] = "[410-shell]$ ";
+char startmsg[] = "Starting shell...\n";
+char exitmsg[] = "Exiting shell...\n";
+char forkerrmsg[] = "Shell: Cannot fork process.\n";
+char waitfailed[] = "wait() failed\n";
+char finished[] = "Process finished\n";
+char too_long[] = "That string is too long.\n";
+char null_check[] = "I've lost null termination!\n";
+char nothing[] = "Readline returned nothing!\n";
+
+/* --- These are global only to avoid stack growth --- */
+/* (unclean, but lets the shell run before swexn() and new_pages()) */
+char buf[MAX_LENGTH];
+char *cmd_argv[MAX_LENGTH];
+char separators[4] = { ' ', '\t', '\n' };
+
+static void print_ls(void);
+static void sort_names(char **names, int num_entries);
+static int mystical_readline(int len, char *buf);
+static int console_height(void);
+
+/* Not all kernels support getchar().
+ *
+ * Try to use it, but if it doesn't work fall back to readline().
+ */
+static int fallback_getchar(void)
+{
+ char buf[2];
+
+ mystical_readline(2, buf);
+
+ return (unsigned char)buf[0]; // cast prevents sign extension
+}
+
+static int try_getchar(void)
+{
+ static int missing_getchar = 0;
+ int c;
+
+ if (missing_getchar || (c = getchar()) < 0) {
+ missing_getchar = 1;
+ return fallback_getchar();
+ }
+ return c;
+}
+#define getchar try_getchar
+
+/* --- Main --- */
+int
+main(int argc, char *argv[])
+{
+ int n;
+ int pid;
+ int res;
+ int j;
+ int ret;
+
+ print(strlen(startmsg), startmsg);
+
+ while(1) {
+
+ bzero(buf, MAX_LENGTH);
+ print(strlen(prompt), prompt);
+ n = mystical_readline(MAX_LENGTH - 1, buf);
+ if (n == 0) {
+ /* Empty result; this shouldn't happen. */
+ print(strlen(nothing), nothing);
+ continue;
+ } else if(n >= MAX_LENGTH) {
+ /* line too big -- kernel declared that it clobbered memory */
+ print(strlen(too_long), too_long);
+ exit(-1);
+ } else if(buf[MAX_LENGTH - 1] != '\0') {
+ /* Overflow -- kernel tapdanced on random memory! */
+ print(strlen(null_check), null_check);
+ exit(-1);
+ }
+
+ buf[n] = '\0';
+ j = 0;
+ if(!(cmd_argv[j++] = strtok(buf, separators))) {
+ continue;
+ }
+ if((strcmp(cmd_argv[0], "exit") == 0)) {
+ print(strlen(exitmsg), exitmsg);
+ exit(0);
+ }
+ if((strcmp(cmd_argv[0], "ls") == 0)) {
+ print_ls();
+ continue;
+ }
+
+ while((cmd_argv[j++] = strtok(NULL, separators)));
+
+ pid = fork();
+ if(pid < 0) {
+ print(sizeof(forkerrmsg), forkerrmsg);
+ continue;
+ }
+ if(pid == 0) {
+ exec(cmd_argv[0], cmd_argv);
+ exit(-1);
+ }
+ else {
+ if((ret = wait(&res)) < 0) {
+ printf("\nshell: wait on process %d failed!\n", pid);
+ }
+ else {
+ printf("\nshell: process %d finished with exit status %d\n", ret, res);
+ }
+ }
+ } /* while loop */
+}
+
+/* emulate the old ls() system call using readfile() */
+int ls(int size, char *buf)
+{
+ int i;
+ int num_files = 0;
+ int amt_read;
+
+ amt_read = readfile(".", buf, size, 0);
+ if (amt_read < 0) return amt_read;
+ /* ls() returned failure if the buffer wasn't big enough for the
+ * entire listing. So if readfile() didn't return short (that is,
+ * there might be more), fail. */
+ if (amt_read == size) return -1;
+
+ /* Now scan through the buffer counting null terminators.
+ * Skip the one at the end. */
+ for (i = 0; i < amt_read - 1; i++) {
+ if (buf[i] == '\0') {
+ num_files++;
+ }
+ }
+
+ return num_files;
+}
+
+static void print_ls()
+{
+ char *buf = NULL;
+ static int size = 16;
+ int num_entries;
+ char ** names = NULL;
+ char *bufptr;
+ int index;
+ int len;
+
+ /* get the array of entries */
+ buf = (char *)malloc(sizeof(char) * size);
+ if (buf == NULL) {
+ printf("Can't malloc(%d)!\n", sizeof(char) * size);
+ goto cleanup;
+ }
+ while ((num_entries = ls(size, buf)) < 0) {
+ size *= 2;
+ char *nbuf = (char *)realloc(buf, sizeof(char) * size);
+ if (nbuf == NULL) {
+ printf("Can't realloc(%d)!\n", sizeof(char) * size);
+ goto cleanup;
+ } else {
+ buf = nbuf;
+ }
+ }
+
+ names = (char **)calloc(num_entries, sizeof(char *));
+ if (names == NULL) {
+ printf("Can't calloc(%d)!\n", num_entries * sizeof(char *));
+ goto cleanup;
+ }
+
+ /* get pointers to each string in the array */
+ bufptr = buf;
+ index = 0;
+ while ((len = strlen(bufptr)) > 0) {
+ names[index++] = bufptr;
+ bufptr += len + 1;
+ }
+
+ sort_names(names, num_entries);
+
+ printf("Listing the user tests\n");
+ for (index = 0; index < num_entries; index++) {
+ if (index != 0 && index % (console_height() - 2) == 0) {
+ printf("Hit a key to continue\n");
+ getchar();
+ }
+ printf("%s\n", names[index]);
+ }
+
+cleanup:
+ if (buf) {
+ free(buf);
+ buf = NULL;
+ }
+ if (names) {
+ free(names);
+ names = NULL;
+ }
+}
+
+static void sort_names(char **names, int num_entries) {
+ /* I invented this cool new sorting algorithm! It's really fast! */
+ int swapped;
+ int i;
+ do {
+ swapped = 0;
+ for (i = 0; i < num_entries - 1; i++) {
+ if (strcmp(names[i], names[i+1]) > 0) {
+ char *tmp = names[i];
+ names[i] = names[i+1];
+ names[i+1] = tmp;
+ swapped = 1;
+ }
+ }
+ } while (swapped);
+}
+
+static int mystical_readline(int len, char *buf) {
+ if (len <= 0) { return 0; }
+
+ buf[0] = '\0';
+ /* If we're in the test harness, this does something very special! */
+ sim_call(0x04108005, buf, len);
+
+ return (buf[0] ? strlen(buf) : readline(len, buf));
+}
+
+static int console_height() {
+ static int console_height = -1;
+
+ if (console_height == -1) {
+ /* determine the height of the console */
+ int curstartrow, curstartcol;
+ get_cursor_pos(&curstartrow, &curstartcol);
+ console_height = 0;
+ while (set_cursor_pos(console_height, 0) == 0) {
+ console_height++;
+ }
+ set_cursor_pos(curstartrow, curstartcol);
+
+ }
+
+ return console_height;
+}
diff --git a/410user/progs/slaughter.c b/410user/progs/slaughter.c
new file mode 100644
index 0000000..9544e60
--- /dev/null
+++ b/410user/progs/slaughter.c
@@ -0,0 +1,144 @@
+/** @file 410user/progs/slaughter.c
+ * @author mtelgars
+ * @author nwf
+ * @brief Runs a lot of copies of a given test.
+ * @public yes
+ * @for p3
+ * @covers fork exec wait set_status vanish
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("slaughter:");
+
+unsigned int width;
+int initial_tid;
+int exit_status;
+
+void __attribute__((noreturn)) slaughter(char **argv, unsigned int depth)
+{
+ int curtid = gettid();
+
+ report_start(START_CMPLT);
+
+ if ( ! depth )
+ {
+ if (exec(argv[0], argv))
+ {
+ lprintf("=====> exec failed from %d!", curtid);
+ exit(-373);
+ }
+ }
+ else
+ {
+ unsigned int i, j, matched;
+ int threads[2*width]; /* not doing anything smart here yet.. */
+ int status, tid;
+
+ for (i = 0; i != 2*width; ++i)
+ {
+ if ( ! (threads[i] = fork()) )
+ {
+ /* alternate immediate exec and slaughter */
+ slaughter(argv, (i % 2) * (depth - 1));
+ }
+ else if (threads[i] < 0) {
+ lprintf("=====> XXX tid %d could not fork (err=%d)!!",
+ curtid,threads[i]);
+ report_end(END_FAIL);
+ exit(exit_status+1);
+ }
+ else
+ {
+ lprintf("=====> Slaugher created TID %d from TID %d",
+ threads[i], curtid);
+ }
+ }
+
+ for (i = 0; i != 2*width; ++i)
+ {
+ tid = wait(&status);
+ if ( tid < 0 )
+ {
+ lprintf("=====> XXX Wait failed in TID %d with %d; bombing out",
+ curtid, tid );
+ report_end(END_FAIL);
+ exit(exit_status+3);
+ }
+ else
+ {
+ matched = 0;
+ for ( j = 0; j != 2*width; ++j )
+ {
+ if ( threads[j] == tid )
+ {
+ matched = 1;
+ threads[j] = -1;
+ break;
+ }
+ }
+ if ( matched == 0 )
+ {
+ lprintf("=====> XXX Wait returned bad TID %d to TID %d; bombing out",
+ tid, curtid );
+ report_end(END_FAIL);
+ exit(exit_status+5);
+ }
+ lprintf("=====> %stid %d gave %svalid status code of %d to tid %d",
+ (status == exit_status) ? "" : "XXX ",
+ tid, (status == exit_status) ? "" : "IN", status, curtid);
+ if ( status != exit_status )
+ {
+ report_end(END_FAIL);
+ exit(exit_status+7);
+ }
+ }
+ }
+ }
+
+ lprintf("=====> Slaughterer %d completed", curtid);
+ report_end(END_SUCCESS);
+ exit(exit_status);
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned int initial_depth;
+ char *default_vec[] = { "print_basic", NULL };
+ char **command_vec;
+
+ if (argc < 5)
+ {
+ printf("slaughter <recursive depth> "
+ "<recursive width> <exit status> <command line>\n");
+ initial_depth = 2;
+ width = 2;
+ exit_status = 0;
+ command_vec = default_vec;
+ printf(" DEFAULTING TO: %d %d %d %s\n", initial_depth, width, exit_status, command_vec[0]);
+ }
+ else if ( ! (width = strtoul(argv[1], NULL, 10)) )
+ {
+ printf(" bad recursive width\n");
+ return -2;
+ }
+ else if ( ! (initial_depth = strtoul(argv[2], NULL, 10)) )
+ {
+ printf(" bad recursive depth\n");
+ return -3;
+ }
+ else
+ {
+ exit_status = strtol(argv[3], NULL, 10);
+ command_vec = &argv[4];
+ }
+
+ slaughter(command_vec, initial_depth);
+ return 0;
+}
diff --git a/410user/progs/sleep_test1.c b/410user/progs/sleep_test1.c
new file mode 100644
index 0000000..290e87a
--- /dev/null
+++ b/410user/progs/sleep_test1.c
@@ -0,0 +1,32 @@
+/** @file 410user/progs/sleep_test1.c
+ * @author zra
+ * @brief Sleeps for amount of time given as an argument.
+ * @public yes
+ * @for p3
+ * @covers sleep
+ * @status done
+ */
+
+/* Includes */
+#include <syscall.h> /* for sleep, getpid */
+#include <stdio.h>
+#include <simics.h> /* for lprintf */
+#include <stdlib.h> /* for atoi, exit */
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("sleep_test1:");
+
+int main(int argc, char *argv[]) {
+ report_start(START_CMPLT);
+ report_misc("before sleeping");
+
+ if (argc == 2)
+ sleep( atoi( argv[1] ) );
+ else
+ sleep( 3 + (gettid() % 27) );
+
+ report_misc("after sleeping");
+ report_end(END_SUCCESS);
+ exit( 42 );
+}
diff --git a/410user/progs/stack_test1.c b/410user/progs/stack_test1.c
new file mode 100644
index 0000000..6b40545
--- /dev/null
+++ b/410user/progs/stack_test1.c
@@ -0,0 +1,47 @@
+/** @file 410user/progs/stack_test1.c
+ * @author efaust
+ * @brief Tests whether auto-stack pages are zeroed.
+ * @public yes
+ * @for p3
+ * @covers autostack
+ * @status done
+ *
+ * Note: If we ever go back to the kernel-level autostack, we should revert
+ * this to the old one.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("stack_test1:");
+
+#define SIZE (65536)
+
+/* Can't you see that I am not afraid */
+void touch_me_babe(char *arr, size_t len)
+{
+ size_t i;
+ for(i = 0; i < len; i++) {
+ arr[i] = i;
+ }
+}
+
+void do_test()
+{
+ char ca[SIZE];
+ touch_me_babe(ca, sizeof(ca));
+}
+
+int main()
+{
+
+ report_start(START_CMPLT);
+
+ do_test();
+ report_misc("stack allocation successful");
+ report_end(END_SUCCESS);
+ exit(42);
+}
diff --git a/410user/progs/swexn_basic_test.c b/410user/progs/swexn_basic_test.c
new file mode 100644
index 0000000..b9e2869
--- /dev/null
+++ b/410user/progs/swexn_basic_test.c
@@ -0,0 +1,77 @@
+/**
+ * @file swexn_basic_test.c
+ * @author bblum
+ * @brief Tests a simple use case for swexn
+ * @public yes
+ * @for p4
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("swexn_basic_test:");
+
+#define STAQ_SIZE (4096)
+char exn_staq[STAQ_SIZE];
+#define EXN_STAQ_TOP ((void *)((unsigned int)(&exn_staq[STAQ_SIZE-7]) & ~(sizeof (int) - 1)))
+
+#define GOOD_MEMORY ((void *)0x40000000)
+
+void handler(void *arg, ureg_t *uregs)
+{
+ int ret;
+
+ REPORT_MISC("Hello from a handler");
+
+ if (uregs == NULL) {
+ REPORT_MISC("what use is a handler without a ureg pointer?");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ ret = new_pages(GOOD_MEMORY, STAQ_SIZE);
+ if (ret < 0) {
+ REPORT_MISC("new_pages failed");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+ *(int *)GOOD_MEMORY = 42;
+ ret = swexn(EXN_STAQ_TOP, handler, NULL, uregs);
+ if (ret < 0) {
+ REPORT_MISC("second swexn rejected");
+ } else {
+ REPORT_MISC("restoring old position failed");
+ }
+ REPORT_END_FAIL;
+ exit(-1);
+ return;
+}
+
+int main()
+{
+ int ret;
+
+ REPORT_START_CMPLT;
+
+ ret = swexn(EXN_STAQ_TOP, handler, NULL, NULL);
+ if (ret < 0) {
+ REPORT_MISC("swexn call rejected");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ /* Invoke handler */
+ ret = *(int *)GOOD_MEMORY;
+
+ if (ret == 0) {
+ REPORT_MISC("handler not run?");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ TEST_PROG_PROGRESS;
+ REPORT_END_SUCCESS;
+ exit(ret);
+}
diff --git a/410user/progs/swexn_cookie_monster.c b/410user/progs/swexn_cookie_monster.c
new file mode 100644
index 0000000..151ce25
--- /dev/null
+++ b/410user/progs/swexn_cookie_monster.c
@@ -0,0 +1,85 @@
+/**
+ * @file swexn_cookie_monster.c
+ * @brief Tests the correct passing of arguments to swexn handlers
+ *
+ * @author mischnal
+ * @for swexn p4
+ * @covers swexn
+ * @public yes
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <syscall.h>
+
+#include "simics.h"
+#include "410_tests.h"
+
+DEF_TEST_NAME("swexn_cookie_monster");
+
+#define SWEXN_STACK_SIZE 2048
+char swexn_stack[SWEXN_STACK_SIZE];
+#define SWEXN_STACK ((void*)(swexn_stack + SWEXN_STACK_SIZE - 8))
+
+void *cookies[] = {(void*)0xfeedbeef, (void*)0x8badf00d, (void*)0xbaddcafe,
+ (void*)0xc0ffee, (void*)0xface, (void*) 0x12345678,
+ (void*)42, (void*)57, (void*)2953575118U};
+int curr_cookie = 0;
+int first_pass = 1;
+
+
+
+void handler(void *arg, ureg_t *uregs)
+{
+ int ret;
+
+ if (cookies[curr_cookie] != arg)
+ {
+ REPORT_MISC(" Cookie incorrect");
+ REPORT_END_FAIL;
+ exit(1);
+ }
+
+ curr_cookie++;
+ if (curr_cookie < sizeof(cookies) / sizeof(cookies[0]))
+ {
+ ret = swexn(SWEXN_STACK, handler, cookies[curr_cookie], uregs);
+ if (ret < 0)
+ {
+ REPORT_MISC(" Failed to install handler");
+ REPORT_END_FAIL;
+ exit(1);
+ }
+ }
+ else
+ {
+ /* Out of cookies */
+ REPORT_END_SUCCESS;
+ exit(0);
+ }
+}
+
+int main(void)
+{
+ int ret;
+ if (first_pass)
+ {
+ REPORT_START_CMPLT;
+ first_pass = 0;
+ }
+
+ ret = swexn(SWEXN_STACK, handler, cookies[curr_cookie], NULL);
+ if (ret < 0)
+ {
+ REPORT_MISC(" Failed to install handler");
+ REPORT_END_FAIL;
+ exit(1);
+ }
+
+ *(volatile int *)NULL = 42;
+
+ /* Should not get here */
+ REPORT_MISC(" Something is very wrong");
+ REPORT_END_FAIL;
+ return 1;
+}
diff --git a/410user/progs/swexn_dispatch.c b/410user/progs/swexn_dispatch.c
new file mode 100644
index 0000000..50764e9
--- /dev/null
+++ b/410user/progs/swexn_dispatch.c
@@ -0,0 +1,55 @@
+/**
+ * @file swexn_dispatch.c
+ * @author bblum
+ * @brief Tests swexn basic function dispatch
+ * @public yes
+ * @for p4
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("swexn_dispatch:");
+
+#define STAQ_SIZE (4096)
+char exn_staq[STAQ_SIZE];
+#define EXN_STAQ_TOP ((void *)(&exn_staq[STAQ_SIZE-4]))
+
+#define COOKIE ((void *)0x0dd0ad9b)
+
+void handler(void *arg, ureg_t *uregs)
+{
+ REPORT_MISC("Hello from a handler");
+
+ if (arg != COOKIE) {
+ /* this fight is not worth fighting */
+ REPORT_MISC("C is for cookie; it's not good enough for me...");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ REPORT_END_SUCCESS;
+ exit(42);
+}
+
+int main()
+{
+ int ret;
+
+ REPORT_START_CMPLT;
+
+ ret = swexn(EXN_STAQ_TOP, handler, COOKIE, NULL);
+ if (ret < 0) {
+ REPORT_MISC("swexn call rejected");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ /* Invoke handler */
+ ret = *(volatile int *)NULL;
+ REPORT_MISC("should not get here!");
+ REPORT_END_FAIL;
+ exit(ret);
+}
diff --git a/410user/progs/swexn_rampage.c b/410user/progs/swexn_rampage.c
new file mode 100644
index 0000000..4203e6d
--- /dev/null
+++ b/410user/progs/swexn_rampage.c
@@ -0,0 +1,96 @@
+/**
+ * @file swexn_rampage.c
+ * @author de0u
+ * @brief Tests a simple use case for swexn
+ * @public yes
+ * @for p3
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+
+#define USER_MEM_START 0x01000000
+#define KERNEL_BOTTOM 0x00100000 // 1 megabyte; below there lie dragons
+
+#define ENOUGH 410
+
+DEF_TEST_NAME("swexn_rampage:");
+
+#define STAQ_SIZE (4096)
+static char exn_staq[STAQ_SIZE];
+#define EXN_STAQ_TOP ((void *)(&exn_staq[STAQ_SIZE-7]))
+
+void install(void);
+void rampage(void);
+void handler(void *arg, ureg_t *uregs);
+
+static unsigned int *top_addr = (unsigned int *)USER_MEM_START - sizeof (unsigned int);
+
+static int events = 0;
+
+static unsigned int start_ticks;
+
+void install(void)
+{
+ int ret;
+
+ ret = swexn(EXN_STAQ_TOP, handler, NULL, NULL);
+ if (ret < 0) {
+ REPORT_MISC("swexn call rejected");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+}
+
+void rampage(void)
+{
+ unsigned int *ip;
+
+ for (ip = top_addr; ip > (unsigned int *)KERNEL_BOTTOM; ip--)
+ *ip = 0;
+
+ REPORT_END_FAIL; // as if
+}
+
+void handler(void *arg, ureg_t *uregs)
+{
+ if (uregs->cause != SWEXN_CAUSE_PAGEFAULT) {
+ report_fmt("bad cause %d", uregs->cause);
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+ if (uregs->cr2 != (unsigned int) top_addr) {
+ report_fmt("bad addr 0x%x", uregs->cr2);
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ TEST_PROG_PROGRESS;
+
+ if (++events == ENOUGH) {
+ report_fmt("ticks %d", get_ticks() - start_ticks);
+ REPORT_END_SUCCESS;
+ exit(0);
+ }
+
+ sleep(15);
+
+ install();
+ rampage();
+}
+
+int main()
+{
+ REPORT_START_CMPLT;
+
+ start_ticks = get_ticks();
+
+ install();
+ rampage();
+
+ REPORT_MISC("handler not run?");
+ REPORT_END_FAIL;
+ exit(-1);
+}
diff --git a/410user/progs/swexn_regs.c b/410user/progs/swexn_regs.c
new file mode 100644
index 0000000..643fb88
--- /dev/null
+++ b/410user/progs/swexn_regs.c
@@ -0,0 +1,65 @@
+/**
+ * @file swexn_regs.c
+ * @brief Tests a case of the validation of uregs.
+ *
+ * @author mischnal
+ * @for swexn p4
+ * @covers swexn
+ * @public yes
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <syscall.h>
+
+#include "simics.h"
+#include "410_tests.h"
+
+DEF_TEST_NAME("swexn_regs");
+
+#define SWEXN_STACK_SIZE 2048
+char swexn_stack[SWEXN_STACK_SIZE];
+#define SWEXN_STACK ((void*)(swexn_stack + SWEXN_STACK_SIZE - 8))
+
+#define EFLAGS_MASK 0x00003000
+
+
+void handler(void *arg, ureg_t *uregs)
+{
+ int ret;
+ REPORT_MISC(" In handler");
+
+ uregs->eflags |= EFLAGS_MASK;
+
+ ret = swexn(SWEXN_STACK, handler, NULL, uregs);
+ if (ret < 0)
+ {
+ REPORT_END_SUCCESS;
+ exit(0);
+ }
+ else
+ {
+ REPORT_END_FAIL;
+ exit(1);
+ }
+}
+
+int main(void)
+{
+ int ret;
+
+ REPORT_START_CMPLT;
+
+ ret = swexn(SWEXN_STACK, handler, NULL, NULL);
+ if (ret < 0)
+ {
+ REPORT_END_FAIL;
+ exit(1);
+ }
+
+ *(volatile int *)NULL = 42;
+
+ /* Should not get here */
+ REPORT_END_FAIL;
+ return 1;
+}
diff --git a/410user/progs/swexn_stands_for_swextensible.c b/410user/progs/swexn_stands_for_swextensible.c
new file mode 100644
index 0000000..31748ec
--- /dev/null
+++ b/410user/progs/swexn_stands_for_swextensible.c
@@ -0,0 +1,58 @@
+/**
+ * @file swexn_stands_for_swextensible.c
+ * @author bblum
+ * @brief Tests what happens when the handler faults
+ * @public yes
+ * @for p4
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("swexn_stands_for_swextensible:");
+
+#define STAQ_SIZE (4096)
+char exn_staq[STAQ_SIZE];
+#define EXN_STAQ_TOP ((void *)(&exn_staq[STAQ_SIZE-11]))
+
+#define BAD_MEMORY ((void *)0x40000000)
+
+volatile int already_called = 0;
+
+void handler(void *arg, ureg_t *uregs)
+{
+ REPORT_MISC("Hello from a handler");
+ if (already_called == 0) {
+ already_called = 1;
+ /* Incur another fault (in a way that won't get optimized). */
+ exit(*(int *)BAD_MEMORY);
+ } else {
+ REPORT_MISC("Not supposed to get called again!");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+ return;
+}
+
+int main()
+{
+ int ret;
+
+ REPORT_START_ABORT;
+
+ ret = swexn(EXN_STAQ_TOP, handler, NULL, NULL);
+ if (ret < 0) {
+ REPORT_MISC("swexn call rejected");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ /* Invoke handler */
+ ret = *(int *)BAD_MEMORY;
+
+ REPORT_MISC("something bad happened!");
+ REPORT_END_FAIL;
+ exit(ret);
+}
diff --git a/410user/progs/swexn_uninstall_test.c b/410user/progs/swexn_uninstall_test.c
new file mode 100644
index 0000000..34d898f
--- /dev/null
+++ b/410user/progs/swexn_uninstall_test.c
@@ -0,0 +1,60 @@
+/**
+ * @file swexn_basic_test.c
+ * @author bblum
+ * @brief Tests uninstalling handlers
+ * @public yes
+ * @for p4
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include "410_tests.h"
+
+DEF_TEST_NAME("swexn_uninstall_test:");
+
+#define STAQ_SIZE (4096)
+char exn_staq[STAQ_SIZE];
+#define EXN_STAQ_TOP ((void *)(&exn_staq[STAQ_SIZE-8]))
+
+#define BAD_MEMORY ((void *)0x40000000)
+
+volatile int success = 0;
+
+void handler(void *arg, ureg_t *uregs)
+{
+ REPORT_MISC("Uh-oh, we weren't supposed to be called!");
+ REPORT_END_FAIL;
+ exit(-1);
+ return;
+}
+
+int main()
+{
+ int ret;
+ void (*x)() = (typeof(x))NULL;
+
+ REPORT_START_ABORT;
+
+ ret = swexn(EXN_STAQ_TOP, handler, NULL, NULL);
+ if (ret < 0) {
+ REPORT_MISC("swexn call rejected");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ /* uninstall */
+ ret = swexn(NULL, NULL, NULL, NULL);
+ if (ret < 0) {
+ REPORT_MISC("swexn call rejected (2)");
+ REPORT_END_FAIL;
+ exit(-1);
+ }
+
+ /* Invoke handler */
+ success = *(int *)BAD_MEMORY;
+
+ REPORT_MISC("D:");
+ REPORT_END_FAIL;
+ exit(-1);
+}
diff --git a/410user/progs/wait_getpid.c b/410user/progs/wait_getpid.c
new file mode 100644
index 0000000..825f10c
--- /dev/null
+++ b/410user/progs/wait_getpid.c
@@ -0,0 +1,48 @@
+/** @file 410user/progs/wait_getpid.c
+ * @author mpa
+ * @brief Tests gettid()/wait()/fork()
+ * @public yes
+ * @for p3
+ * @covers gettid wait fork set_status vanish
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("wait_getpid:");
+
+int main()
+{
+ int pid, status;
+
+ report_start(START_CMPLT);
+
+ pid = fork();
+
+ if (pid < 0) {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ if (pid == 0) {
+ pid = gettid();
+ exit(pid);
+ report_end(END_FAIL);
+ }
+ if (wait(&status) != pid) {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ if (status != pid) {
+ report_end(END_FAIL);
+ exit(-1);
+ }
+
+ report_end(END_SUCCESS);
+ exit(0);
+}
diff --git a/410user/progs/wild_test1.c b/410user/progs/wild_test1.c
new file mode 100644
index 0000000..bc11ecc
--- /dev/null
+++ b/410user/progs/wild_test1.c
@@ -0,0 +1,31 @@
+/** @file 410user/progs/wild_test1.c
+ * @author zra
+ * @brief Tests thread death by unnatural causes.
+ * @public yes
+ * @for p2 p3
+ * @covers faults
+ * @status done
+ */
+
+/* Includes */
+#include <syscall.h> /* was for exit */
+#include <stdlib.h> /* for exit */
+#include <stdio.h>
+#include <simics.h> /* for lprintf */
+
+#include "410_tests.h"
+DEF_TEST_NAME("wild_test1:");
+
+/* Main */
+int main(void)
+{
+ int *wild = (int *)0x31337000;
+
+ REPORT_START_ABORT;
+
+ *wild = 0x2badd00d;
+
+ REPORT_END_FAIL;
+
+ exit( -1 );
+}
diff --git a/410user/progs/work.c b/410user/progs/work.c
new file mode 100644
index 0000000..46c34f9
--- /dev/null
+++ b/410user/progs/work.c
@@ -0,0 +1,58 @@
+/** @file 410user/progs/work.c
+ * @author acrichto
+ * @brief Factors some numbers in some tasks
+ * @public yes
+ * @for p4-smp
+ * @status done
+ */
+
+#include <410_tests.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include <stdint.h>
+
+DEF_TEST_NAME("work:");
+
+#define AMT 50
+#define MAX 8000000
+
+int work(uint32_t num) {
+ uint32_t i;
+ uint32_t factors = 0;
+
+ for (i = 1; i <= num; i++) {
+ if (num % i == 0) factors ++;
+ }
+
+ return factors;
+}
+
+int main() {
+ int ticks = get_ticks();
+ int i;
+ int last = 0;
+ srand(0x1401);
+
+ for (i = 0; i < AMT; i++) {
+
+ int next = rand() % MAX;
+ int pid = fork();
+ REPORT_ON_ERR(pid);
+ if (pid == 0) {
+ return work(next);
+ }
+ printf("factoring: %u\n", next);
+ }
+ print(1, ">");
+ for (i = 0; i < AMT; i++) {
+ wait(NULL);
+ if (i * 79 / AMT > last) {
+ print(3, "\b=>");
+ last++;
+ }
+ }
+
+ printf("\nticks taken: %d\n", get_ticks() - ticks);
+ return 0;
+}
diff --git a/410user/progs/yield_desc_mkrun.c b/410user/progs/yield_desc_mkrun.c
new file mode 100644
index 0000000..080689d
--- /dev/null
+++ b/410user/progs/yield_desc_mkrun.c
@@ -0,0 +1,68 @@
+/** @file 410user/progs/yield_desc_mkrun.c
+ * @author mpa
+ * @brief Tests yield() and deschedule()/make_runnable()
+ * @public yes
+ * @for p3
+ * @covers yield deschedule make_runnable fork set_status vanish
+ * @status done
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "410_tests.h"
+#include <report.h>
+
+DEF_TEST_NAME("yield_desc_mkrun:");
+
+int main() {
+ int parenttid, childtid, error;
+
+ report_start(START_CMPLT);
+
+ parenttid = gettid();
+ childtid = fork();
+
+ if (childtid < 0) {
+ lprintf("cannot fork()");
+ goto fail;
+ }
+
+ if (childtid == 0) {
+ /* child */
+
+ /* Wait until the process deschedules itself */
+ while(yield(parenttid) == 0) {
+ report_misc("parent not asleep yet");
+ }
+
+ report_misc("parent presumably asleep");
+
+ /* Wake parent back up */
+ if((error = make_runnable(parenttid)) != 0) {
+ lprintf("make_runnable() failed %d in child", error);
+ goto fail;
+ }
+ report_misc("parent should be awake");
+ } else {
+ /* parent */
+
+ int reject = 0;
+ if((error = deschedule(&reject)) != 0) {
+ lprintf("deschedule() failed %d in parent", error);
+ goto fail;
+ }
+
+ /* wait() would be better, but we're not testing wait() here */
+ yield(childtid);
+ yield(childtid);
+ yield(childtid);
+ report_end(END_SUCCESS);
+ }
+
+ exit(0);
+
+fail:
+ report_end(END_FAIL);
+ exit(1);
+}
diff --git a/410user/user.mk b/410user/user.mk
new file mode 100644
index 0000000..bd7deec
--- /dev/null
+++ b/410user/user.mk
@@ -0,0 +1,60 @@
+################# TARGET-SPECIFIC RULES #################
+
+# "You are not expected to understand this."
+$(STUUDIR)/libthread/panic.o: CFLAGS+=-Wno-missing-noreturn
+$(STUUDIR)/libsyscall/syscall.o: CFLAGS+=-Wno-missing-noreturn
+
+$(410UDIR)/exec2obj.dep: INCLUDES=$(KINCLUDES)
+$(410UDIR)/exec2obj.dep: CFLAGS=-m32 -Wall -Werror
+
+# This wants to use the system standard library and everything. I'm not sure how this ever
+# worked; probably only because of the use of -I-...
+$(410UDIR)/exec2obj: $(410UDIR)/exec2obj.c
+ 410-gcc -m32 -I. -Wall -Werror -o $@ $^
+# $(CC) -m32 -iquote 410kern/inc -Wall -Werror -o $@ $^
+# $(CC) -m32 $(KINCLUDES) -Wall -Werror -o $@ $^
+
+ifeq (1,$(DO_INCLUDE_DEPS))
+-include $(410UDIR)/exec2obj.dep
+endif
+
+410UCLEANS+=$(410UDIR)/exec2obj $(410UDIR)/exec2obj.dep
+
+$(PROGS:%=$(BUILDDIR)/%) :
+$(BUILDDIR)/%.strip : $(BUILDDIR)/%
+ strip -o $@ $<
+
+.INTERMEDIATE: $(PROGS:%=$(BUILDDIR)/%.strip)
+
+# Generate a directory listing file so the shell can implement ls
+$(BUILDDIR)/__DIR_LISTING__: $(PROGS:%=$(BUILDDIR)/%.strip) \
+ $(FILES:%=$(BUILDDIR)/%)
+ (printf "%s\0" $(sort $(PROGS) $(FILES)); printf "\0") > $(BUILDDIR)/__DIR_LISTING__
+
+$(BUILDDIR)/user_apps.o: $(410UDIR)/exec2obj $(BUILDDIR)/__DIR_LISTING__ \
+ $(PROGS:%=$(BUILDDIR)/%.strip) \
+ $(FILES:%=$(BUILDDIR)/%)
+ ( cd $(BUILDDIR); \
+ $(PROJROOT)/$(410UDIR)/exec2obj __DIR_LISTING__ $(PROGS) $(FILES)) | \
+ $(AS) --32 -o $@
+
+include $(410UDIR)/$(UPROGDIR)/progs.mk
+
+include $(patsubst %.a,$(410UDIR)/%/user.mk,$(410USER_LIBS_EARLY) $(410USER_LIBS_LATE))
+
+################# STUDENT LIBRARY RULES #################
+
+STUU_THREAD_OBJS := $(THREAD_OBJS:%=$(STUUDIR)/libthread/%)
+ALL_STUUOBJS += $(STUU_THREAD_OBJS)
+STUUCLEANS += $(STUUDIR)/libthread.a
+$(STUUDIR)/libthread.a: $(STUU_THREAD_OBJS)
+
+STUU_SYSCALL_OBJS := $(SYSCALL_OBJS:%=$(STUUDIR)/libsyscall/%)
+ALL_STUUOBJS += $(STUU_SYSCALL_OBJS)
+STUUCLEANS += $(STUUDIR)/libsyscall.a
+$(STUUDIR)/libsyscall.a: $(STUU_SYSCALL_OBJS)
+
+STUU_AUTOSTACK_OBJS := $(AUTOSTACK_OBJS:%=$(STUUDIR)/libautostack/%)
+ALL_STUUOBJS += $(STUU_AUTOSTACK_OBJS)
+STUUCLEANS += $(STUUDIR)/libautostack.a
+$(STUUDIR)/libautostack.a: $(STUU_AUTOSTACK_OBJS)