ref: 3ccc8224be30ed01a30a4d92ca868df4e98a13fd
parent: a4a1a88a70d82facefdd19b66ebc372e28adb146
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Jun 4 17:11:17 EDT 2016
aml: implement ToInteger() and Match() instructions
--- a/sys/src/libaml/aml.c
+++ b/sys/src/libaml/aml.c
@@ -144,11 +144,12 @@
Oadd, Osub, Omod, Omul, Odiv, Oshl, Oshr, Oand, Onand, Oor,
Onor, Oxor, Onot, Olbit, Orbit, Oinc, Odec,
Oland, Olor, Olnot, Oleq, Olgt, Ollt,
- Oindex, Omutex, Oevent,
+ Oindex, Omatch, Omutex, Oevent,
Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8,
Oif, Oelse, Owhile, Obreak, Oret, Ocall,
Ostore, Oderef, Osize, Oref, Ocref, Ocat,
Oacq, Orel, Ostall, Osleep, Oload, Ounload,
+ Otoint,
};
static Op optab[];
@@ -1155,7 +1156,7 @@
case 0x01:
return mki(1);
case 0xFF:
- return mki(-1);
+ return mki(~0ULL);
}
return nil;
}
@@ -1442,14 +1443,12 @@
return nil;
}
-static void*
-evalcmp(void)
+static vlong
+cmp1(void *a, void *b)
{
- void *a, *b;
- int tag, c;
+ vlong c;
+ int tag;
- a = FP->arg[0];
- b = FP->arg[1];
if(a == nil || TAG(a) == 'i'){
c = ival(a) - ival(b);
} else {
@@ -1457,20 +1456,27 @@
if(b == nil || TAG(b) != tag)
b = copy(tag, b);
if(TAG(b) != tag)
- return nil; /* botch */
+ return -1; /* botch */
switch(tag){
default:
- return nil; /* botch */
+ return -1; /* botch */
case 's':
c = strcmp((char*)a, (char*)b);
break;
case 'b':
- if((c = SIZE(a) - SIZE(b)) == 0)
+ c = SIZE(a) - SIZE(b);
+ if(c == 0)
c = memcmp(a, b, SIZE(a));
break;
}
}
+ return c;
+}
+static void*
+evalcmp(void)
+{
+ vlong c = cmp1(FP->arg[0], FP->arg[1]);
switch(FP->op - optab){
case Oleq:
if(c == 0) return mki(1);
@@ -1613,7 +1619,7 @@
Field *f;
void *p;
Ref *r;
- int x;
+ uvlong x;
x = ival(FP->arg[1]);
if(p = deref(FP->arg[0])) switch(TAG(p)){
@@ -1622,7 +1628,7 @@
break;
/* no break */
case 'b':
- if(x < 0 || x >= SIZE(p))
+ if(x >= SIZE(p))
break;
f = mk('u', sizeof(Field));
f->reg = p;
@@ -1631,7 +1637,7 @@
store(f, FP->arg[2]);
return f;
case 'p':
- if(x < 0 || x >= (SIZE(p)/sizeof(void*)))
+ if(x >= (SIZE(p)/sizeof(void*)))
break;
if(TAG(FP->arg[0]) == 'A' || TAG(FP->arg[0]) == 'L')
r = mk(TAG(FP->arg[0]), sizeof(Ref));
@@ -1645,7 +1651,38 @@
return nil;
}
+static int
+match1(int op, void *a, void *b)
+{
+ vlong c = cmp1(a, b);
+ switch(op){
+ case 0: return 1;
+ case 1: return c == 0;
+ case 2: return c <= 0;
+ case 3: return c < 0;
+ case 4: return c >= 0;
+ case 5: return c > 0;
+ }
+ return 0;
+}
+
static void*
+evalmatch(void)
+{
+ void **p = FP->arg[0];
+ if(p != nil && TAG(p) == 'p'){
+ uvlong i, n = SIZE(p)/sizeof(void*);
+ int o1 = ival(FP->arg[1]), o2 = ival(FP->arg[3]);
+ for(i=ival(FP->arg[5]); i<n; i++){
+ void *a = deref(p[i]);
+ if(match1(o1, a, FP->arg[2]) && match1(o2, a, FP->arg[4]))
+ return mki(i);
+ }
+ }
+ return mki(~0ULL);
+}
+
+static void*
evalcondref(void)
{
void *s;
@@ -1835,6 +1872,24 @@
return nil;
}
+static void*
+evalconv(void)
+{
+ void *r;
+
+ r = nil;
+ switch(FP->op - optab){
+ case Otoint:
+ if(FP->arg[0] != nil && TAG(FP->arg[0]) == 's')
+ r = mki(strtoull((char*)FP->arg[0], 0, 0));
+ else
+ r = mki(ival(FP->arg[0]));
+ break;
+ }
+ store(r, FP->arg[1]);
+ return r;
+}
+
static Op optab[] = {
[Obad] "", "", evalbad,
[Onop] "Noop", "", evalnop,
@@ -1914,6 +1969,7 @@
[Ostore] "Store", "*@", evalstore,
[Oindex] "Index", "@i@", evalindex,
+ [Omatch] "Match", "*1*1*i", evalmatch,
[Osize] "SizeOf", "*", evalsize,
[Oref] "RefOf", "@", evaliarg0,
[Ocref] "CondRefOf", "@@", evalcondref,
@@ -1926,6 +1982,8 @@
[Osleep] "Sleep", "i", evalsleep,
[Oload] "Load", "*@}", evalload,
[Ounload] "Unload", "@", evalnop,
+
+ [Otoint] "ToInteger", "*@", evalconv,
};
static uchar octab1[] = {
@@ -1946,9 +2004,9 @@
/* 70 */ Ostore, Oref, Oadd, Ocat, Osub, Oinc, Odec, Omul,
/* 78 */ Odiv, Oshl, Oshr, Oand, Onand, Oor, Onor, Oxor,
/* 80 */ Onot, Olbit, Orbit, Oderef, Obad, Omod, Obad, Osize,
-/* 88 */ Oindex, Obad, Ocfld4, Ocfld2, Ocfld1, Ocfld0, Obad, Ocfld8,
+/* 88 */ Oindex, Omatch, Ocfld4, Ocfld2, Ocfld1, Ocfld0, Obad, Ocfld8,
/* 90 */ Oland, Olor, Olnot, Oleq, Olgt, Ollt, Obad, Obad,
-/* 98 */ Obad, Obad, Obad, Obad, Obad, Obad, Obad, Obad,
+/* 98 */ Obad, Otoint, Obad, Obad, Obad, Obad, Obad, Obad,
/* A0 */ Oif, Oelse, Owhile, Onop, Oret, Obreak, Obad, Obad,
/* A8 */ Obad, Obad, Obad, Obad, Obad, Obad, Obad, Obad,
/* B0 */ Obad, Obad, Obad, Obad, Obad, Obad, Obad, Obad,