# [ZILF] Bitwise operations

I want to do some bitwise operations in the ZILF game I’m working on, but I’m not 100% sure how I’d do this. Am I right in thinking that I can do bitwise AND with `<BAND a b>` and bitwise OR with `<BOR a b>`? What does `BCOM` (mentioned, but not defined, in Learning ZIL) do? Is it the bitwise NOT? Last, but not least, am I right in thinking that the engine does not have a bitwise XOR operation and that I’ll want to do `<BAND <BOR a b> <NOT <BAND a b>>>` (and what should I put where `NOT` is?)

I went ahead and wrote some code (line numbers added for clarity):

``````01 ;"implement XOR-mapped rotation in ZIL."
02
03 ;"Forward XOR map values: 2083, 4166, 8332, 16664, 33329, 3136, 6273, 12546, 25092, 50185, 32817, 2113, 4226, 8452, 16904, 33809."
04 <CONSTANT FORWARDXORTABLE
05 	<TABLE 2083 4166 8332 16664 -32207 3136 6273 12546 25092 -15351 -32719 2113 4226 8452 16904 -31727>
06 >
07
08 ;"Reverse XOR map values: 40033, 14530, 29060, 58120, 50704, 4161, 8322, 16644, 33288, 1040, 37953, 46307, 27078, 54156, 42776, 20016."
09 <CONSTANT REVERSEXORTABLE
10	<TABLE -25503 14530 29060 -7416 -14832 4161 8322 16644 -32248 1040 -27583 -19229 27078 -11380 -22760 20016>
11 >
12
13 ;"Powers of two, signed."
14 <CONSTANT POWERSOFTWO
15 	<TABLE 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 -32768>
16 >
17
18 ;"Compute the forward XOR-mapped rotation."
19 <ROUTINE FORWARDXOR (INPUT "AUX" (XORBIT 0) (OUTPUT 0) (CURRENTXORENTRY 0))
20 	<REPEAT ()
21 		<COND (<BAND .INPUT <GET POWERSOFTWO .XORBIT>>)
22 			<SET CURRENTXORENTRY <GET FORWARDXORTABLE .XORBIT>>
23 			<SET OUTPUT <BAND <BOR .OUTPUT .CURRENTXORENTRY> <BCOM <BAND .OUTPUT .CURRENTXORENTRY>>>>
24 		>
25		<COND (<IGRTR? XORBIT 15>) <RETURN>>
26 	>
27 	<RETURN .OUTPUT>
28 >
``````

Explaining what it’s supposed to do is a bit complicated, but I can if that’d be useful. I’m making a more elementary error, though, as reported by ZILF:

``````[warning ZIL0507] ..\..\Broad But Shallow Sea.zil:23: COND: condition is always true
[warning ZIL0505] ..\..\Broad But Shallow Sea.zil:21: COND: clauses after else part will never be evaluated
[warning ZIL0507] ..\..\Broad But Shallow Sea.zil:27: COND: condition is always true
``````

I’m sure it’s something simple and silly, but I’m still learning. What’m I doing wrong?

The Z-Machine unfortunately does not have an XOR opcode. I don’t know ZIL so can’t help with the rest.

`BCOM` stands for Bitwise COMplement: in other words, flipping every bit in a word (like C’s `~` operator).

So yes, `<BAND <BOR ,X ,Y> <BCOM <BAND ,X ,Y>>>` gets you a bitwise XOR in four instructions, which I think is the best you can do on the Z-machine (and is honestly fast enough that, if it’s becoming a problem, you have bigger fish to fry).

Bonus: I think the equivalent in Inform assembly syntax would be:

``````@and x y -> sp;
@not sp -> sp;
@or x y -> sp;
@and sp sp -> sp;
``````

But I haven’t done Inform assembly in a while, and when I have it’s usually been for Glulx, which just has a straight-up `@xor` opcode.

1 Like

@bitxor actually ;). That assembly looks right. You can do it as a statement in Inform 6 too.

Okay, so I had the right idea. I’m still having those warnings when I compile, though. Where’d I go wrong?

Oh, you just have some mistakes in your `COND` syntax. `COND` works like this:

``````<COND
(predicate1 expr expr expr)
(predicate2 expr expr)
(predicate3 expr expr expr expr)
>
``````

In other words, the expressions have to be inside the `LIST` with the condition. In your case, you want something like:

``````<COND
( <BAND something> <SET something> <SET something> )
>
<COND
( <IGRTR? something> <RETURN> )
>``````
1 Like

Thank you kindly!