bitwise arith, more loops

master
Ondřej Hruška 3 years ago
parent 0f5eda0def
commit c02b3599fb
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 1
      include/fh_error.h
  2. 3
      include/fh_runtime.h
  3. 133
      src/fh_builtins.c
  4. 1
      src/fh_error.c
  5. 22
      src/fh_mem.c

@ -24,6 +24,7 @@ enum fh_error {
FH_ERR_INTERNAL, FH_ERR_INTERNAL,
FH_ERR_UNKNOWN_WORD, FH_ERR_UNKNOWN_WORD,
FH_ERR_ILLEGAL_FETCH, FH_ERR_ILLEGAL_FETCH,
FH_ERR_ILLEGAL_STORE,
FH_ERR_DIV_BY_ZERO, FH_ERR_DIV_BY_ZERO,
FH_ERR_MAX, FH_ERR_MAX,
}; };

@ -141,7 +141,7 @@ struct fh_thread_s {
/** Data heap */ /** Data heap */
uint8_t heap[HEAP_SIZE]; uint8_t heap[HEAP_SIZE];
size_t heap_top; size_t heap_top; // aka "HERE"
/** Compile buffer, used for both word data and literals */ /** Compile buffer, used for both word data and literals */
uint8_t compile[COMPILED_BUFFER_SIZE]; uint8_t compile[COMPILED_BUFFER_SIZE];
@ -175,6 +175,7 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w);
// SFR and magic addresses are "negative" // SFR and magic addresses are "negative"
#define MAGICADDR_INTERACTIVE 0xFFFFFFFFULL #define MAGICADDR_INTERACTIVE 0xFFFFFFFFULL
#define MAGICADDR_BASE 0xFFFFBA5EULL #define MAGICADDR_BASE 0xFFFFBA5EULL
#define MAGICADDR_HERE 0xFFFF4E7EULL
#define MAGICADDR_UNRESOLVED 0xFFFFFBADULL #define MAGICADDR_UNRESOLVED 0xFFFFFBADULL
/** Get a value rounded up to multiple of word size */ /** Get a value rounded up to multiple of word size */

@ -99,6 +99,39 @@ static enum fh_error w_star(struct fh_thread_s *fh, const struct fh_word_s *w)
return FH_OK; return FH_OK;
} }
static enum fh_error w_and(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
uint32_t a = 0, b = 0;
TRY(ds_pop(fh, &a));
TRY(ds_pop(fh, &b));
TRY(ds_push(fh, a & b));
return FH_OK;
}
static enum fh_error w_or(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
uint32_t a = 0, b = 0;
TRY(ds_pop(fh, &a));
TRY(ds_pop(fh, &b));
TRY(ds_push(fh, a | b));
return FH_OK;
}
static enum fh_error w_xor(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
uint32_t a = 0, b = 0;
TRY(ds_pop(fh, &a));
TRY(ds_pop(fh, &b));
TRY(ds_push(fh, a ^ b));
return FH_OK;
}
static enum fh_error w_zero_less(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_zero_less(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
@ -268,6 +301,41 @@ static enum fh_error w_slash(struct fh_thread_s *fh, const struct fh_word_s *w)
return FH_OK; return FH_OK;
} }
static enum fh_error w_abs(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
uint32_t a = 0;
TRY(ds_pop(fh, &a));
int32_t sa = (int32_t) a; // TODO is this right?
if (sa < 0) { sa = -sa; }
TRY(ds_push(fh, sa));
return FH_OK;
}
static enum fh_error w_invert(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
uint32_t a = 0;
TRY(ds_pop(fh, &a));
TRY(ds_push(fh, ~a));
return FH_OK;
}
static enum fh_error w_negate(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
uint32_t a = 0;
TRY(ds_pop(fh, &a));
TRY(ds_push(fh, (uint32_t) (-(uint32_t) a)));
return FH_OK;
}
static enum fh_error w_slash_mod(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_slash_mod(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
@ -863,6 +931,23 @@ static enum fh_error w_repeat(struct fh_thread_s *fh, const struct fh_word_s *w)
return FH_OK; return FH_OK;
} }
static enum fh_error w_again(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
struct fh_instruction_s instr;
ENSURE_STATE(FH_STATE_COMPILE);
uint32_t destaddr = 0;
TRY(cs_pop(fh, &destaddr));
instr_init(&instr, FH_INSTR_JUMP, destaddr);
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
return FH_OK;
}
static enum fh_error wp_setbase(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error wp_setbase(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
fh_setbase(fh, w->param); fh_setbase(fh, w->param);
@ -980,6 +1065,40 @@ static enum fh_error w_aligned(struct fh_thread_s *fh, const struct fh_word_s *w
return FH_OK; return FH_OK;
} }
static enum fh_error w_allot(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
uint32_t count = 0;
TRY(ds_pop(fh, &count));
TRY(fh_heap_reserve(fh, count, NULL));
return FH_OK;
}
static enum fh_error w_comma(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
if (fh->heap_top & 3) {
LOGE("HERE not aligned before 'comma'");
return FH_ERR_ILLEGAL_STORE;
}
uint32_t value = 0;
TRY(ds_pop(fh, &value));
TRY(fh_heap_put(fh, &value, CELL));
return FH_OK;
}
static enum fh_error w_align(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
fh->heap_top = WORDALIGNED(fh->heap_top);
return FH_OK;
}
/** Add pointers to built-in word handlers to a runtime struct */ /** Add pointers to built-in word handlers to a runtime struct */
enum fh_error register_builtin_words(struct fh_thread_s *fh) enum fh_error register_builtin_words(struct fh_thread_s *fh)
{ {
@ -1002,6 +1121,9 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
{"2!", w_two_store, 0, 0}, {"2!", w_two_store, 0, 0},
{"2@", w_two_fetch, 0, 0}, {"2@", w_two_fetch, 0, 0},
{"aligned", w_aligned, 0, 0}, {"aligned", w_aligned, 0, 0},
{"allot", w_allot, 0, 0},
{"align", w_align, 0, 0},
{",", w_comma, 0, 0},
// TODO +! // TODO +!
// TODO pictured numbers (#) // TODO pictured numbers (#)
// TODO tick // TODO tick
@ -1011,16 +1133,22 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
{"decimal", wp_setbase, 0, 10}, {"decimal", wp_setbase, 0, 10},
{"hex", wp_setbase, 0, 16}, {"hex", wp_setbase, 0, 16},
{"base", wp_const, 0, MAGICADDR_BASE}, {"base", wp_const, 0, MAGICADDR_BASE},
{"here", wp_const, 0, MAGICADDR_HERE},
{"false", wp_const, 0, 0}, {"false", wp_const, 0, 0},
{"true", wp_const, 0, 0xFFFFFFFF}, {"true", wp_const, 0, 0xFFFFFFFF},
{"depth", w_depth, 0, 0},
{"+", w_plus, 0, 0}, {"+", w_plus, 0, 0},
{"-", w_minus, 0, 0}, {"-", w_minus, 0, 0},
{"*", w_star, 0, 0}, {"*", w_star, 0, 0},
{"*/", w_star_slash, 0, 0}, {"*/", w_star_slash, 0, 0},
{"*/mod", w_star_slash_mod, 0, 0}, {"*/mod", w_star_slash_mod, 0, 0},
{"or", w_or, 0, 0},
{"and", w_and, 0, 0},
{"xor", w_xor, 0, 0},
{"/", w_slash, 0, 0}, {"/", w_slash, 0, 0},
{"abs", w_abs, 0, 0},
{"/mod", w_slash_mod, 0, 0}, {"/mod", w_slash_mod, 0, 0},
{"invert", w_invert, 0, 0},
{"negate", w_negate, 0, 0},
{"0<", w_zero_less, 0, 0}, {"0<", w_zero_less, 0, 0},
{"0=", w_zero_equals, 0, 0}, {"0=", w_zero_equals, 0, 0},
{"0<>", w_zero_not_equals, 0, 0}, {"0<>", w_zero_not_equals, 0, 0},
@ -1042,8 +1170,8 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
/* Stack manip */ /* Stack manip */
{"drop", w_drop, 0, 0}, {"drop", w_drop, 0, 0},
{"dup", w_dupe, 0, 0}, {"dup", w_dupe, 0, 0},
{"nip", w_nip, 0, 0},
{"?dup", w_question_dupe, 0, 0}, {"?dup", w_question_dupe, 0, 0},
{"nip", w_nip, 0, 0},
{"over", w_over, 0, 0}, {"over", w_over, 0, 0},
{"swap", w_swap, 0, 0}, {"swap", w_swap, 0, 0},
{"rot", w_rot, 0, 0}, {"rot", w_rot, 0, 0},
@ -1082,6 +1210,7 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
{"begin", w_begin, 1, 0}, {"begin", w_begin, 1, 0},
{"while", w_while, 1, 0}, {"while", w_while, 1, 0},
{"repeat", w_repeat, 1, 0}, {"repeat", w_repeat, 1, 0},
{"again", w_again, 1, 0},
{"until", w_until, 1, 0}, {"until", w_until, 1, 0},
/* Syntax */ /* Syntax */
{":", w_colon, 0, 0}, {":", w_colon, 0, 0},

@ -17,6 +17,7 @@ static const char *errornames[FH_ERR_MAX] = {
[FH_ERR_INTERNAL] = "INTERNAL", [FH_ERR_INTERNAL] = "INTERNAL",
[FH_ERR_UNKNOWN_WORD] = "UNKNOWN_WORD", [FH_ERR_UNKNOWN_WORD] = "UNKNOWN_WORD",
[FH_ERR_ILLEGAL_FETCH] = "ILLEGAL_FETCH", [FH_ERR_ILLEGAL_FETCH] = "ILLEGAL_FETCH",
[FH_ERR_ILLEGAL_STORE] = "ILLEGAL_STORE",
[FH_ERR_DIV_BY_ZERO] = "DIV_BY_ZERO", [FH_ERR_DIV_BY_ZERO] = "DIV_BY_ZERO",
}; };

@ -16,7 +16,10 @@ enum fh_error fh_fetch(struct fh_thread_s *fh, uint32_t addr, uint32_t *dst)
case MAGICADDR_BASE: case MAGICADDR_BASE:
*dst = fh->base; *dst = fh->base;
break; break;
// TODO more magic
case MAGICADDR_HERE:
*dst = fh->heap_top;
break;
default: default:
if (addr & 3) { if (addr & 3) {
@ -52,18 +55,21 @@ enum fh_error fh_store(struct fh_thread_s *fh, uint32_t addr, uint32_t val)
case MAGICADDR_BASE: case MAGICADDR_BASE:
fh_setbase(fh, val); fh_setbase(fh, val);
break; break;
// TODO more magic
case MAGICADDR_HERE:
LOGE("HERE is read-only!");
return FH_ERR_ILLEGAL_STORE;
default: default:
if (addr & 3) { if (addr & 3) {
LOGE("Address 0x%08x is not aligned!", addr); LOGE("Address 0x%08x is not aligned!", addr);
return FH_ERR_ILLEGAL_FETCH; return FH_ERR_ILLEGAL_STORE;
} }
if (addr <= HEAP_SIZE - 4) { if (addr <= HEAP_SIZE - 4) {
*((uint32_t*)&fh->heap[addr]) = val; *((uint32_t*)&fh->heap[addr]) = val;
} else { } else {
LOGE("Address 0x%08x too high!", addr); LOGE("Address 0x%08x too high!", addr);
return FH_ERR_ILLEGAL_FETCH; return FH_ERR_ILLEGAL_STORE;
} }
} }
@ -95,7 +101,9 @@ enum fh_error fh_heap_reserve(
return FH_ERR_HEAP_FULL; return FH_ERR_HEAP_FULL;
} }
*addr = p; if (addr) {
*addr = p;
}
fh->heap_top = WORDALIGNED(p + len); fh->heap_top = WORDALIGNED(p + len);
@ -137,7 +145,9 @@ enum fh_error fh_compile_reserve(
return FH_ERR_HEAP_FULL; return FH_ERR_HEAP_FULL;
} }
*addr = p; if (addr) {
*addr = p;
}
fh->compile_top = WORDALIGNED(p + len); fh->compile_top = WORDALIGNED(p + len);

Loading…
Cancel
Save