| /* tag: C implementation of all forth primitives |
| * |
| * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer |
| * |
| * See the file "COPYING" for further information about |
| * the copyright and warranty status of this work. |
| */ |
| |
| /* |
| * dup ( x -- x x ) |
| */ |
| |
| static void fdup(void) |
| { |
| const cell tmp = GETTOS(); |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * 2dup ( x1 x2 -- x1 x2 x1 x2 ) |
| */ |
| |
| static void twodup(void) |
| { |
| cell tmp = GETITEM(1); |
| PUSH(tmp); |
| tmp = GETITEM(1); |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * ?dup ( x -- 0 | x x ) |
| */ |
| |
| static void isdup(void) |
| { |
| const cell tmp = GETTOS(); |
| if (tmp) |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * over ( x y -- x y x ) |
| */ |
| |
| static void over(void) |
| { |
| const cell tmp = GETITEM(1); |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * 2over ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 ) |
| */ |
| |
| static void twoover(void) |
| { |
| const cell tmp = GETITEM(3); |
| const cell tmp2 = GETITEM(2); |
| PUSH(tmp); |
| PUSH(tmp2); |
| } |
| |
| /* |
| * pick ( xu ... x1 x0 u -- xu ... x1 x0 xu ) |
| */ |
| |
| static void pick(void) |
| { |
| const cell u = POP(); |
| if (dstackcnt >= u) { |
| ucell tmp = dstack[dstackcnt - u]; |
| PUSH(tmp); |
| } else { |
| /* underrun */ |
| } |
| } |
| |
| |
| /* |
| * drop ( x -- ) |
| */ |
| |
| static void drop(void) |
| { |
| POP(); |
| } |
| |
| /* |
| * 2drop ( x1 x2 -- ) |
| */ |
| |
| static void twodrop(void) |
| { |
| POP(); |
| POP(); |
| } |
| |
| |
| /* |
| * nip ( x1 x2 -- x2 ) |
| */ |
| |
| static void nip(void) |
| { |
| const cell tmp = POP(); |
| POP(); |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * roll ( xu ... x1 x0 u -- xu-1... x1 x0 xu ) |
| */ |
| |
| static void roll(void) |
| { |
| const cell u = POP(); |
| if (dstackcnt >= u) { |
| int i; |
| const cell xu = dstack[dstackcnt - u]; |
| for (i = dstackcnt - u; i < dstackcnt; i++) { |
| dstack[i] = dstack[i + 1]; |
| } |
| dstack[dstackcnt] = xu; |
| } else { |
| /* Stack underrun */ |
| } |
| } |
| |
| |
| /* |
| * rot ( x1 x2 x3 -- x2 x3 x1 ) |
| */ |
| |
| static void rot(void) |
| { |
| const cell tmp = POP(); |
| const cell tmp2 = POP(); |
| const cell tmp3 = POP(); |
| PUSH(tmp2); |
| PUSH(tmp); |
| PUSH(tmp3); |
| } |
| |
| |
| /* |
| * -rot ( x1 x2 x3 -- x3 x1 x2 ) |
| */ |
| |
| static void minusrot(void) |
| { |
| const cell tmp = POP(); |
| const cell tmp2 = POP(); |
| const cell tmp3 = POP(); |
| PUSH(tmp); |
| PUSH(tmp3); |
| PUSH(tmp2); |
| } |
| |
| |
| /* |
| * swap ( x1 x2 -- x2 x1 ) |
| */ |
| |
| static void swap(void) |
| { |
| const cell tmp = POP(); |
| const cell tmp2 = POP(); |
| PUSH(tmp); |
| PUSH(tmp2); |
| } |
| |
| |
| /* |
| * 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 ) |
| */ |
| |
| static void twoswap(void) |
| { |
| const cell tmp = POP(); |
| const cell tmp2 = POP(); |
| const cell tmp3 = POP(); |
| const cell tmp4 = POP(); |
| PUSH(tmp2); |
| PUSH(tmp); |
| PUSH(tmp4); |
| PUSH(tmp3); |
| } |
| |
| |
| /* |
| * >r ( x -- ) (R: -- x ) |
| */ |
| |
| static void tor(void) |
| { |
| ucell tmp = POP(); |
| #ifdef CONFIG_DEBUG_RSTACK |
| printk(" >R: %x\n", tmp); |
| #endif |
| PUSHR(tmp); |
| } |
| |
| |
| /* |
| * r> ( -- x ) (R: x -- ) |
| */ |
| |
| static void rto(void) |
| { |
| ucell tmp = POPR(); |
| #ifdef CONFIG_DEBUG_RSTACK |
| printk(" R>: %x\n", tmp); |
| #endif |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * r@ ( -- x ) (R: x -- x ) |
| */ |
| |
| static void rfetch(void) |
| { |
| PUSH(GETTORS()); |
| } |
| |
| |
| /* |
| * depth ( -- u ) |
| */ |
| |
| static void depth(void) |
| { |
| const cell tmp = dstackcnt; |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * depth! ( ... u -- x1 x2 .. xu ) |
| */ |
| |
| static void depthwrite(void) |
| { |
| ucell tmp = POP(); |
| dstackcnt = tmp; |
| } |
| |
| |
| /* |
| * rdepth ( -- u ) |
| */ |
| |
| static void rdepth(void) |
| { |
| const cell tmp = rstackcnt; |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * rdepth! ( u -- ) ( R: ... -- x1 x2 .. xu ) |
| */ |
| |
| static void rdepthwrite(void) |
| { |
| ucell tmp = POP(); |
| rstackcnt = tmp; |
| } |
| |
| |
| /* |
| * + ( nu1 nu2 -- sum ) |
| */ |
| |
| static void plus(void) |
| { |
| cell tmp = POP() + POP(); |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * - ( nu1 nu2 -- diff ) |
| */ |
| |
| static void minus(void) |
| { |
| const cell nu2 = POP(); |
| const cell nu1 = POP(); |
| PUSH(nu1 - nu2); |
| } |
| |
| |
| /* |
| * * ( nu1 nu2 -- prod ) |
| */ |
| |
| static void mult(void) |
| { |
| const cell nu2 = POP(); |
| const cell nu1 = POP(); |
| PUSH(nu1 * nu2); |
| } |
| |
| |
| /* |
| * u* ( u1 u2 -- prod ) |
| */ |
| |
| static void umult(void) |
| { |
| const ucell tmp = (ucell) POP() * (ucell) POP(); |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * mu/mod ( n1 n2 -- rem quot.l quot.h ) |
| */ |
| |
| static void mudivmod(void) |
| { |
| const ucell b = POP(); |
| const ducell a = DPOP(); |
| #ifdef NEED_FAKE_INT128_T |
| fprintf(stderr, "mudivmode called\n"); |
| exit(-1); |
| #else |
| PUSH(a % b); |
| DPUSH(a / b); |
| #endif |
| } |
| |
| |
| /* |
| * abs ( n -- u ) |
| */ |
| |
| static void forthabs(void) |
| { |
| const cell tmp = GETTOS(); |
| if (tmp < 0) { |
| POP(); |
| PUSH(-tmp); |
| } |
| } |
| |
| |
| /* |
| * negate ( n1 -- n2 ) |
| */ |
| |
| static void negate(void) |
| { |
| const cell tmp = POP(); |
| PUSH(-tmp); |
| } |
| |
| |
| /* |
| * max ( n1 n2 -- n1|n2 ) |
| */ |
| |
| static void max(void) |
| { |
| const cell tmp = POP(); |
| const cell tmp2 = POP(); |
| PUSH((tmp > tmp2) ? tmp : tmp2); |
| } |
| |
| |
| /* |
| * min ( n1 n2 -- n1|n2 ) |
| */ |
| |
| static void min(void) |
| { |
| const cell tmp = POP(); |
| const cell tmp2 = POP(); |
| PUSH((tmp < tmp2) ? tmp : tmp2); |
| } |
| |
| |
| /* |
| * lshift ( x1 u -- x2 ) |
| */ |
| |
| static void lshift(void) |
| { |
| const ucell u = POP(); |
| const ucell x1 = POP(); |
| PUSH(x1 << u); |
| } |
| |
| |
| /* |
| * rshift ( x1 u -- x2 ) |
| */ |
| |
| static void rshift(void) |
| { |
| const ucell u = POP(); |
| const ucell x1 = POP(); |
| PUSH(x1 >> u); |
| } |
| |
| |
| /* |
| * >>a ( x1 u -- x2 ) ?? |
| */ |
| |
| static void rshifta(void) |
| { |
| const cell u = POP(); |
| const cell x1 = POP(); |
| PUSH(x1 >> u); |
| } |
| |
| |
| /* |
| * and ( x1 x2 -- x3 ) |
| */ |
| |
| static void and(void) |
| { |
| const cell x1 = POP(); |
| const cell x2 = POP(); |
| PUSH(x1 & x2); |
| } |
| |
| |
| /* |
| * or ( x1 x2 -- x3 ) |
| */ |
| |
| static void or(void) |
| { |
| const cell x1 = POP(); |
| const cell x2 = POP(); |
| PUSH(x1 | x2); |
| } |
| |
| |
| /* |
| * xor ( x1 x2 -- x3 ) |
| */ |
| |
| static void xor(void) |
| { |
| const cell x1 = POP(); |
| const cell x2 = POP(); |
| PUSH(x1 ^ x2); |
| } |
| |
| |
| /* |
| * invert ( x1 -- x2 ) |
| */ |
| |
| static void invert(void) |
| { |
| const cell x1 = POP(); |
| PUSH(x1 ^ -1); |
| } |
| |
| |
| /* |
| * d+ ( d1 d2 -- d.sum ) |
| */ |
| |
| static void dplus(void) |
| { |
| const dcell d2 = DPOP(); |
| const dcell d1 = DPOP(); |
| #ifdef NEED_FAKE_INT128_T |
| fprintf(stderr, "dplus called\n"); |
| exit(-1); |
| #else |
| DPUSH(d1 + d2); |
| #endif |
| } |
| |
| |
| /* |
| * d- ( d1 d2 -- d.diff ) |
| */ |
| |
| static void dminus(void) |
| { |
| const dcell d2 = DPOP(); |
| const dcell d1 = DPOP(); |
| #ifdef NEED_FAKE_INT128_T |
| fprintf(stderr, "dminus called\n"); |
| exit(-1); |
| #else |
| DPUSH(d1 - d2); |
| #endif |
| } |
| |
| |
| /* |
| * m* ( ?? -- ) |
| */ |
| |
| static void mmult(void) |
| { |
| const cell u2 = POP(); |
| const cell u1 = POP(); |
| #ifdef NEED_FAKE_INT128_T |
| fprintf(stderr, "mmult called\n"); |
| exit(-1); |
| #else |
| DPUSH((dcell) u1 * u2); |
| #endif |
| } |
| |
| |
| /* |
| * um* ( u1 u2 -- d.prod ) |
| */ |
| |
| static void ummult(void) |
| { |
| const ucell u2 = POP(); |
| const ucell u1 = POP(); |
| #ifdef NEED_FAKE_INT128_T |
| fprintf(stderr, "ummult called\n"); |
| exit(-1); |
| #else |
| DPUSH((ducell) u1 * u2); |
| #endif |
| } |
| |
| |
| /* |
| * @ ( a-addr -- x ) |
| */ |
| |
| static void fetch(void) |
| { |
| const ucell *aaddr = (ucell *)cell2pointer(POP()); |
| PUSH(read_ucell(aaddr)); |
| } |
| |
| |
| /* |
| * c@ ( addr -- byte ) |
| */ |
| |
| static void cfetch(void) |
| { |
| const u8 *aaddr = (u8 *)cell2pointer(POP()); |
| PUSH(read_byte(aaddr)); |
| } |
| |
| |
| /* |
| * w@ ( waddr -- w ) |
| */ |
| |
| static void wfetch(void) |
| { |
| const u16 *aaddr = (u16 *)cell2pointer(POP()); |
| PUSH(read_word(aaddr)); |
| } |
| |
| |
| /* |
| * l@ ( qaddr -- quad ) |
| */ |
| |
| static void lfetch(void) |
| { |
| const u32 *aaddr = (u32 *)cell2pointer(POP()); |
| PUSH(read_long(aaddr)); |
| } |
| |
| |
| /* |
| * ! ( x a-addr -- ) |
| */ |
| |
| static void store(void) |
| { |
| const ucell *aaddr = (ucell *)cell2pointer(POP()); |
| const ucell x = POP(); |
| #ifdef CONFIG_DEBUG_INTERNAL |
| printk("!: %lx : %lx -> %lx\n", aaddr, read_ucell(aaddr), x); |
| #endif |
| write_ucell(aaddr,x); |
| } |
| |
| |
| /* |
| * +! ( nu a-addr -- ) |
| */ |
| |
| static void plusstore(void) |
| { |
| const ucell *aaddr = (ucell *)cell2pointer(POP()); |
| const cell nu = POP(); |
| write_cell(aaddr,read_cell(aaddr)+nu); |
| } |
| |
| |
| /* |
| * c! ( byte addr -- ) |
| */ |
| |
| static void cstore(void) |
| { |
| const u8 *aaddr = (u8 *)cell2pointer(POP()); |
| const ucell byte = POP(); |
| #ifdef CONFIG_DEBUG_INTERNAL |
| printk("c!: %x = %x\n", aaddr, byte); |
| #endif |
| write_byte(aaddr, byte); |
| } |
| |
| |
| /* |
| * w! ( w waddr -- ) |
| */ |
| |
| static void wstore(void) |
| { |
| const u16 *aaddr = (u16 *)cell2pointer(POP()); |
| const u16 word = POP(); |
| write_word(aaddr, word); |
| } |
| |
| |
| /* |
| * l! ( quad qaddr -- ) |
| */ |
| |
| static void lstore(void) |
| { |
| const u32 *aaddr = (u32 *)cell2pointer(POP()); |
| const u32 longval = POP(); |
| write_long(aaddr, longval); |
| } |
| |
| |
| /* |
| * = ( x1 x2 -- equal? ) |
| */ |
| |
| static void equals(void) |
| { |
| cell tmp = (POP() == POP()); |
| PUSH(-tmp); |
| } |
| |
| |
| /* |
| * > ( n1 n2 -- greater? ) |
| */ |
| |
| static void greater(void) |
| { |
| cell tmp = ((cell) POP() < (cell) POP()); |
| PUSH(-tmp); |
| } |
| |
| |
| /* |
| * < ( n1 n2 -- less? ) |
| */ |
| |
| static void less(void) |
| { |
| cell tmp = ((cell) POP() > (cell) POP()); |
| PUSH(-tmp); |
| } |
| |
| |
| /* |
| * u> ( u1 u2 -- unsigned-greater? ) |
| */ |
| |
| static void ugreater(void) |
| { |
| cell tmp = ((ucell) POP() < (ucell) POP()); |
| PUSH(-tmp); |
| } |
| |
| |
| /* |
| * u< ( u1 u2 -- unsigned-less? ) |
| */ |
| |
| static void uless(void) |
| { |
| cell tmp = ((ucell) POP() > (ucell) POP()); |
| PUSH(-tmp); |
| } |
| |
| |
| /* |
| * sp@ ( -- stack-pointer ) |
| */ |
| |
| static void spfetch(void) |
| { |
| // FIXME this can only work if the stack pointer |
| // is within range. |
| ucell tmp = pointer2cell(&(dstack[dstackcnt])); |
| PUSH(tmp); |
| } |
| |
| |
| /* |
| * move ( src-addr dest-addr len -- ) |
| */ |
| |
| static void fmove(void) |
| { |
| ucell count = POP(); |
| void *dest = (void *)cell2pointer(POP()); |
| const void *src = (const void *)cell2pointer(POP()); |
| memmove(dest, src, count); |
| } |
| |
| |
| /* |
| * fill ( addr len byte -- ) |
| */ |
| |
| static void ffill(void) |
| { |
| ucell value = POP(); |
| ucell count = POP(); |
| void *src = (void *)cell2pointer(POP()); |
| memset(src, value, count); |
| } |
| |
| |
| /* |
| * unaligned-w@ ( addr -- w ) |
| */ |
| |
| static void unalignedwordread(void) |
| { |
| const unsigned char *addr = (const unsigned char *) cell2pointer(POP()); |
| PUSH(unaligned_read_word(addr)); |
| } |
| |
| |
| /* |
| * unaligned-w! ( w addr -- ) |
| */ |
| |
| static void unalignedwordwrite(void) |
| { |
| const unsigned char *addr = (const unsigned char *) cell2pointer(POP()); |
| u16 w = POP(); |
| unaligned_write_word(addr, w); |
| } |
| |
| |
| /* |
| * unaligned-l@ ( addr -- quad ) |
| */ |
| |
| static void unalignedlongread(void) |
| { |
| const unsigned char *addr = (const unsigned char *) cell2pointer(POP()); |
| PUSH(unaligned_read_long(addr)); |
| } |
| |
| |
| /* |
| * unaligned-l! ( quad addr -- ) |
| */ |
| |
| static void unalignedlongwrite(void) |
| { |
| unsigned char *addr = (unsigned char *) cell2pointer(POP()); |
| u32 l = POP(); |
| unaligned_write_long(addr, l); |
| } |
| |
| /* |
| * here ( -- dictionary-pointer ) |
| */ |
| |
| static void here(void) |
| { |
| PUSH(pointer2cell(dict) + dicthead); |
| #ifdef CONFIG_DEBUG_INTERNAL |
| printk("here: %x\n", pointer2cell(dict) + dicthead); |
| #endif |
| } |
| |
| /* |
| * here! ( new-dict-pointer -- ) |
| */ |
| |
| static void herewrite(void) |
| { |
| ucell tmp = POP(); /* converted pointer */ |
| dicthead = tmp - pointer2cell(dict); |
| #ifdef CONFIG_DEBUG_INTERNAL |
| printk("here!: new value: %x\n", tmp); |
| #endif |
| } |
| |
| |
| /* |
| * emit ( char -- ) |
| */ |
| |
| static void emit(void) |
| { |
| #ifndef FCOMPILER |
| cell tmp = POP(); |
| putchar(tmp); |
| #else |
| (void) POP(); |
| #endif |
| } |
| |
| |
| /* |
| * key? ( -- pressed? ) |
| */ |
| |
| static void iskey(void) |
| { |
| PUSH((cell) availchar()); |
| } |
| |
| |
| /* |
| * key ( -- char ) |
| */ |
| |
| static void key(void) |
| { |
| while (!availchar()); |
| #ifdef FCOMPILER |
| PUSH(get_inputbyte()); |
| #else |
| PUSH(getchar()); |
| #endif |
| } |
| |
| |
| /* |
| * ioc@ ( reg -- val ) |
| */ |
| |
| static void iocfetch(void) |
| { |
| #ifndef FCOMPILER |
| cell reg = POP(); |
| PUSH(inb(reg)); |
| #else |
| (void)POP(); |
| PUSH(0); |
| #endif |
| } |
| |
| |
| /* |
| * iow@ ( reg -- val ) |
| */ |
| |
| static void iowfetch(void) |
| { |
| #ifndef FCOMPILER |
| cell reg = POP(); |
| PUSH(inw(reg)); |
| #else |
| (void)POP(); |
| PUSH(0); |
| #endif |
| } |
| |
| /* |
| * iol@ ( reg -- val ) |
| */ |
| |
| static void iolfetch(void) |
| { |
| #ifndef FCOMPILER |
| cell reg = POP(); |
| PUSH(inl(reg)); |
| #else |
| (void)POP(); |
| PUSH(0); |
| #endif |
| } |
| |
| |
| /* |
| * ioc! ( val reg -- ) |
| */ |
| |
| static void iocstore(void) |
| { |
| #ifndef FCOMPILER |
| cell reg = POP(); |
| cell val = POP(); |
| |
| outb(reg, val); |
| #else |
| (void)POP(); |
| (void)POP(); |
| #endif |
| } |
| |
| |
| /* |
| * iow! ( val reg -- ) |
| */ |
| |
| static void iowstore(void) |
| { |
| #ifndef FCOMPILER |
| cell reg = POP(); |
| cell val = POP(); |
| |
| outw(reg, val); |
| #else |
| (void)POP(); |
| (void)POP(); |
| #endif |
| } |
| |
| |
| /* |
| * iol! ( val reg -- ) |
| */ |
| |
| static void iolstore(void) |
| { |
| #ifndef FCOMPILER |
| ucell reg = POP(); |
| ucell val = POP(); |
| |
| outl(reg, val); |
| #else |
| (void)POP(); |
| (void)POP(); |
| #endif |
| } |
| |
| /* |
| * i ( -- i ) |
| */ |
| |
| static void loop_i(void) |
| { |
| PUSH(rstack[rstackcnt]); |
| } |
| |
| /* |
| * j ( -- i ) |
| */ |
| |
| static void loop_j(void) |
| { |
| PUSH(rstack[rstackcnt - 2]); |
| } |