commit 6a893ca80685ed2cba5cae763d15e6743410374b
parent 8b1d75c6eee6e6152e86192627b900842c67c602
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sat, 25 Mar 2023 09:19:33 -0400
halcc: lts() ltu()
Diffstat:
5 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/fs/comp/c/egen.fs b/fs/comp/c/egen.fs
@@ -77,11 +77,14 @@ assign _<<=, _<<, assign _>>=, _>>,
\ To avoid W juggling, we check if our right operand is W. If it is, no need
\ for juggling, all we need is to invert the condition we use.
-: cmpop doer swap , , does> ( left right 'conds )
+\ data: unsigned cond, unsigned swapped cond, signed cond, signed swapped cond
+: cmpop doer 4 for ' execute , next does> ( left right 'conds )
+ over Result unsigned? not if CELLSZ << + then
over Result :isW? if CELLSZ + @ >r swap else @ >r then ( left right )
Result :hal# over Result :?>W cmp, r> C>W, ;
-Z) Z) cmpop _==, NZ) NZ) cmpop _!=,
-<) >=) cmpop _<, <=) >) cmpop _<=, >) <=) cmpop _>, >=) <) cmpop _>=,
+cmpop _==, Z) Z) Z) Z) cmpop _!=, NZ) NZ) NZ) NZ)
+cmpop _<, <) >=) s<) s>=) cmpop _<=, <=) >) s<=) s>)
+cmpop _>, >) <=) s>) s<=) cmpop _>=, >=) <) s>=) s<)
\ Our implementation of "x ? y : z" suffers a significant limitation because
\ we're single pass: by the time _? is called, it's possible that code
diff --git a/fs/comp/c/expr.fs b/fs/comp/c/expr.fs
@@ -32,13 +32,14 @@ struct[ Result
sfield basesz \ size, in bytes of the base type
sfield lvl \ lvl changed applied within the expression
sfield blvl \ Bottom Level
+ sfield unsigned?
\ There can only be one result using W at once. Whenever a W result is
\ created, it takes the lock. If it's already taken, there's an error.
0 value currentW \ link to Result
: :Wfree# currentW if abort" W is already taken!" then ;
- : :new ( arg type -- res ) SZ syspad :[ , , CELLSZ , 0 , 0 , syspad :] ;
+ : :new ( arg type -- res ) SZ syspad :[ , , CELLSZ , 0 , 0 , 0 , syspad :] ;
: :none ( -- res ) 0 NONE :new ;
: :const ( n -- res ) CONST :new ;
: :W ( -- res ) :Wfree# 0 W :new dup to currentW ;
@@ -61,6 +62,7 @@ struct[ Result
: :cdecl ( cdecl -- res )
dup CDECL :new ( cdecl res )
over CDecl type typesize over to basesz
+ over typeunsigned? over to unsigned?
over bi CDecl lvl | CDecl nbelem bool + over to blvl ( cdecl res )
swap CDecl nbelem if dup :& -1 over to+ blvl then ;
diff --git a/fs/tests/comp/c/cc.fs b/fs/tests/comp/c/cc.fs
@@ -53,9 +53,9 @@ nullstr expected 16 []= #
forbreak 10 #eq
forcontinue 9 #eq
forempty \ no crash
-testend \s
-1 0 lts #
-1 0 ltu not #
+testend \s
0 boolnot 1 #eq
42 boolnot 0 #eq
S" foobar" 2 get8b 'o' #eq
diff --git a/fs/tests/comp/c/test2.c b/fs/tests/comp/c/test2.c
@@ -215,3 +215,9 @@ int forcontinue() {
void forempty() {
for (;1;) return;
}
+int lts(int a, int b) {
+ return a < b;
+}
+int ltu(unsigned int a, unsigned int b) {
+ return a < b;
+}
diff --git a/posix/vm.c b/posix/vm.c
@@ -69,6 +69,10 @@ no assembler to complete the HAL to "full" level later. It's all in there.
#define CONDNC 0x81
#define CONDA 0x02 // above (unsigned gt)
#define CONDNA 0x82
+#define CONDLT 0x03 // signed
+#define CONDNLT 0x83
+#define CONDGT 0x04 // signed
+#define CONDNGT 0x84
#define EMETA_8B 0x10
#define EMETA_16B 0x11
@@ -85,6 +89,7 @@ struct VM {
dword *dst;
byte Z;
byte C;
+ byte SC; // signed C
byte compiling;
byte hbankidx;
byte mem[MEMSZ];
@@ -235,6 +240,8 @@ static int checkcond(byte cond) {
case CONDZ: r = vm.Z; break;
case CONDC: r = vm.C; break;
case CONDA: r = !vm.C && !vm.Z; break;
+ case CONDLT: r = vm.SC; break;
+ case CONDGT: r = !vm.SC && !vm.Z; break;
}
if (cond&0x80) r = !r;
return r;
@@ -274,7 +281,9 @@ static void WSTORE() { GETA; sdr(a, *vm.dst); }
static void WSWAP() { GETA; dword n; n = gdr(a); sdr(a, *vm.dst); *vm.dst = n; }
static void MADDN() { GETA; dword n=gpc(); n += gdr(a); sdr(a, n); vm.Z = n == 0; }
static void WCMP() {
- GETA; dword n = gdr(a); vm.Z = n == *vm.dst; vm.C = *vm.dst < n; }
+ GETA; dword n = gdr(a);
+ vm.Z = n == *vm.dst; vm.C = *vm.dst < n;
+ vm.SC = (*vm.dst+0x80000000) < (n+0x80000000); }
static void WIFETCH() { GETA; *vm.dst = gd(gdr(a)); }
static void WISTORE() { GETA; sdr(gdr(a), *vm.dst); }
static void WADD() { GETA; *vm.dst += gdr(a); vm.Z = *vm.dst == 0; }
@@ -933,6 +942,8 @@ static void buildsysdict() {
sysconst("C)", CONDC); sysconst("NC)", CONDNC);
sysconst("<)", CONDC); sysconst(">=)", CONDNC);
sysconst(">)", CONDA); sysconst("<=)", CONDNA);
+ sysconst("s<)", CONDLT); sysconst("s>=)", CONDNLT);
+ sysconst("s>)", CONDGT); sysconst("s<=)", CONDNGT);
for (int i=0; i<OPCNT-0x28; i++) {
if (opnames[i]) wentry(opnames[i], i+0x28);
}