/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcode/private.h>
#include <fcdriver/fcdriver.h>
#define LF_PER_XF (sizeof (xforth_t)/sizeof (lforth_t))
#define WF_PER_XF (sizeof (xforth_t)/sizeof (wforth_t))
void unaligned_xfetch(fcode_env_t *);
void unaligned_xstore(fcode_env_t *);
static void xbsplit(fcode_env_t *);
xforth_t
pop_xforth(fcode_env_t *env)
{
if (sizeof (xforth_t) == sizeof (fstack_t))
return (POP(DS));
return ((xforth_t)pop_double(env));
}
xforth_t
peek_xforth(fcode_env_t *env)
{
xforth_t d;
d = pop_xforth(env);
push_xforth(env, d);
return (d);
}
void
push_xforth(fcode_env_t *env, xforth_t a)
{
if (sizeof (xforth_t) == sizeof (fstack_t))
PUSH(DS, a);
else
push_double(env, (dforth_t)a);
}
/*
* bxjoin ( b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi -- o )
*/
static void
bxjoin(fcode_env_t *env)
{
union {
uchar_t b_bytes[sizeof (xforth_t)];
xforth_t b_xf;
} b;
int i;
CHECK_DEPTH(env, sizeof (xforth_t), "bxjoin");
for (i = 0; i < sizeof (xforth_t); i++)
b.b_bytes[i] = POP(DS);
push_xforth(env, b.b_xf);
}
/*
* <l@ ( qaddr -- n )
*/
static void
lsfetch(fcode_env_t *env)
{
s_lforth_t *addr;
xforth_t a;
CHECK_DEPTH(env, 1, "<l@");
addr = (s_lforth_t *)POP(DS);
a = *addr;
push_xforth(env, a);
}
/*
* lxjoin ( quad.lo quad.hi -- o )
*/
static void
lxjoin(fcode_env_t *env)
{
union {
lforth_t b_lf[LF_PER_XF];
xforth_t b_xf;
} b;
int i;
CHECK_DEPTH(env, LF_PER_XF, "lxjoin");
for (i = 0; i < LF_PER_XF; i++)
b.b_lf[i] = POP(DS);
push_xforth(env, b.b_xf);
}
/*
* wxjoin ( w.lo w.2 w.3 w.hi -- o )
*/
static void
wxjoin(fcode_env_t *env)
{
union {
wforth_t b_wf[WF_PER_XF];
xforth_t b_xf;
} b;
int i;
CHECK_DEPTH(env, WF_PER_XF, "wxjoin");
for (i = 0; i < WF_PER_XF; i++)
b.b_wf[i] = POP(DS);
push_xforth(env, b.b_xf);
}
/*
* x, ( o -- )
*/
static void
xcomma(fcode_env_t *env)
{
CHECK_DEPTH(env, 1, "x,");
DEBUGF(COMMA, dump_comma(env, "x,"));
PUSH(DS, (fstack_t)HERE);
unaligned_xstore(env);
set_here(env, HERE + sizeof (xforth_t), "xcomma");
}
/*
* x@ ( xaddr -- o )
*/
void
xfetch(fcode_env_t *env)
{
xforth_t *addr;
xforth_t a;
CHECK_DEPTH(env, 1, "x@");
addr = (xforth_t *)POP(DS);
a = *addr;
push_xforth(env, a);
}
/*
* x! ( o xaddr -- )
*/
void
xstore(fcode_env_t *env)
{
xforth_t *addr;
xforth_t a;
CHECK_DEPTH(env, 2, "x!");
addr = (xforth_t *)POP(DS);
a = pop_xforth(env);
*addr = a;
}
/*
* /x ( -- n )
*/
static void
slash_x(fcode_env_t *env)
{
PUSH(DS, sizeof (xforth_t));
}
/*
* /x* ( nu1 -- nu2 )
*/
static void
slash_x_times(fcode_env_t *env)
{
CHECK_DEPTH(env, 1, "/x*");
TOS *= sizeof (xforth_t);
}
/*
* xa+ ( addr1 index -- addr2 )
*/
static void
xa_plus(fcode_env_t *env)
{
fstack_t index;
CHECK_DEPTH(env, 2, "xa+");
index = POP(DS);
TOS += index * sizeof (xforth_t);
}
/*
* xa1+ ( addr1 -- addr2 )
*/
static void
xa_one_plus(fcode_env_t *env)
{
CHECK_DEPTH(env, 1, "xa1+");
TOS += sizeof (xforth_t);
}
/*
* xbflip ( oct1 -- oct2 )
*/
void
xbflip(fcode_env_t *env)
{
union {
uchar_t b_bytes[sizeof (xforth_t)];
xforth_t b_xf;
} b, c;
int i;
CHECK_DEPTH(env, 1, "xbflip");
b.b_xf = pop_xforth(env);
for (i = 0; i < sizeof (xforth_t); i++)
c.b_bytes[i] = b.b_bytes[(sizeof (xforth_t) - 1) - i];
push_xforth(env, c.b_xf);
}
void
unaligned_xfetch(fcode_env_t *env)
{
fstack_t addr;
int i;
CHECK_DEPTH(env, 1, "unaligned-x@");
addr = POP(DS);
for (i = 0; i < sizeof (xforth_t); i++, addr++) {
PUSH(DS, addr);
cfetch(env);
}
bxjoin(env);
xbflip(env);
}
void
unaligned_xstore(fcode_env_t *env)
{
fstack_t addr;
int i;
CHECK_DEPTH(env, 2, "unaligned-x!");
addr = POP(DS);
xbsplit(env);
for (i = 0; i < sizeof (xforth_t); i++, addr++) {
PUSH(DS, addr);
cstore(env);
}
}
/*
* xbflips ( xaddr len -- )
*/
static void
xbflips(fcode_env_t *env)
{
fstack_t len, addr;
int i;
CHECK_DEPTH(env, 2, "xbflips");
len = POP(DS);
addr = POP(DS);
for (i = 0; i < len; i += sizeof (xforth_t),
addr += sizeof (xforth_t)) {
PUSH(DS, addr);
unaligned_xfetch(env);
xbflip(env);
PUSH(DS, addr);
unaligned_xstore(env);
}
}
/*
* xbsplit ( o -- b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi )
*/
static void
xbsplit(fcode_env_t *env)
{
union {
uchar_t b_bytes[sizeof (xforth_t)];
xforth_t b_xf;
} b;
int i;
CHECK_DEPTH(env, 1, "xbsplit");
b.b_xf = pop_xforth(env);
for (i = 0; i < sizeof (xforth_t); i++)
PUSH(DS, b.b_bytes[(sizeof (xforth_t) - 1) - i]);
}
/*
* xlflip ( oct1 -- oct2 )
*/
void
xlflip(fcode_env_t *env)
{
union {
lforth_t b_lf[LF_PER_XF];
xforth_t b_xf;
} b, c;
int i;
CHECK_DEPTH(env, 1, "xlflip");
b.b_xf = pop_xforth(env);
for (i = 0; i < LF_PER_XF; i++)
c.b_lf[i] = b.b_lf[(LF_PER_XF - 1) - i];
push_xforth(env, c.b_xf);
}
/*
* xlflips ( xaddr len -- )
*/
static void
xlflips(fcode_env_t *env)
{
fstack_t len, addr;
int i;
CHECK_DEPTH(env, 2, "xlflips");
len = POP(DS);
addr = POP(DS);
for (i = 0; i < len; i += sizeof (xforth_t),
addr += sizeof (xforth_t)) {
PUSH(DS, addr);
unaligned_xfetch(env);
xlflip(env);
PUSH(DS, addr);
unaligned_xstore(env);
}
}
/*
* xlsplit ( o -- quad.lo quad.hi )
*/
static void
xlsplit(fcode_env_t *env)
{
union {
lforth_t b_lf[LF_PER_XF];
xforth_t b_xf;
} b;
int i;
CHECK_DEPTH(env, 1, "xlsplit");
b.b_xf = pop_xforth(env);
for (i = 0; i < LF_PER_XF; i++)
PUSH(DS, b.b_lf[(LF_PER_XF - 1) - i]);
}
/*
* xwflip ( oct1 -- oct2 )
*/
static void
xwflip(fcode_env_t *env)
{
union {
wforth_t b_wf[WF_PER_XF];
xforth_t b_xf;
} b, c;
int i;
CHECK_DEPTH(env, 1, "xwflip");
b.b_xf = pop_xforth(env);
for (i = 0; i < WF_PER_XF; i++)
c.b_wf[i] = b.b_wf[(WF_PER_XF - 1) - i];
push_xforth(env, c.b_xf);
}
/*
* xwflips ( xaddr len -- )
*/
static void
xwflips(fcode_env_t *env)
{
fstack_t len, addr;
int i;
CHECK_DEPTH(env, 2, "xwflips");
len = POP(DS);
addr = POP(DS);
for (i = 0; i < len; i += sizeof (xforth_t),
addr += sizeof (xforth_t)) {
PUSH(DS, addr);
unaligned_xfetch(env);
xwflip(env);
PUSH(DS, addr);
unaligned_xstore(env);
}
}
/*
* xwsplit ( o -- w.lo w.2 w.3 w.hi )
*/
static void
xwsplit(fcode_env_t *env)
{
union {
wforth_t b_wf[WF_PER_XF];
xforth_t b_xf;
} b;
int i;
CHECK_DEPTH(env, 1, "xwsplit");
b.b_xf = pop_xforth(env);
for (i = 0; i < WF_PER_XF; i++)
PUSH(DS, b.b_wf[(WF_PER_XF - 1) - i]);
}
#pragma init(_init)
static void
_init(void)
{
fcode_env_t *env = initial_env;
ASSERT(env);
NOTICE;
P1275(0x241, 0, "bxjoin", bxjoin);
P1275(0x242, 0, "<l@", lsfetch);
P1275(0x243, 0, "lxjoin", lxjoin);
P1275(0x244, 0, "wxjoin", wxjoin);
P1275(0x245, 0, "x,", xcomma);
P1275(0x246, 0, "x@", xfetch);
P1275(0x247, 0, "x!", xstore);
P1275(0x248, 0, "/x", slash_x);
P1275(0x249, 0, "/x*", slash_x_times);
P1275(0x24a, 0, "xa+", xa_plus);
P1275(0x24b, 0, "xa1+", xa_one_plus);
P1275(0x24c, 0, "xbflip", xbflip);
P1275(0x24d, 0, "xbflips", xbflips);
P1275(0x24e, 0, "xbsplit", xbsplit);
P1275(0x24f, 0, "xlflip", xlflip);
P1275(0x250, 0, "xlflips", xlflips);
P1275(0x251, 0, "xlsplit", xlsplit);
P1275(0x252, 0, "xwflip", xwflip);
P1275(0x253, 0, "xwflips", xwflips);
P1275(0x254, 0, "xwsplit", xwsplit);
FORTH(0, "unaligned-x@", unaligned_xfetch);
FORTH(0, "unaligned-x!", unaligned_xstore);
}