Josef “Jeff” Sipek

Exclusive Or Character

A couple of years ago I blogged about the CCS instruction in the Apollo Guidance Computer. Today I want to tell you about the XC instruction from the System/360 ISA.

Many ISAs have some sort of xor instruction. The 360 is no different. It offers several different xor instructions which differ in the type of operands that they operate on. In all cases, the operation they perform could be summarized as (using C syntax):

A ^= B;

That is one of the operands is used as both a source and a destination.

There are the boring X (reg ^= memory), XR (reg ^= reg), and XI (reg ^= immediate). Then there is XC which is what inspired this post. XC, or Exclusive Or Character, takes two memory locations and a length and performs what appears as byte by byte xor of the two buffers. (The hardware is smart enough to operate on bigger chunks of memory but the effect is as if it was done byte at a time.) In assembly XC looks like:

XC d1(l,b1),d2(b2)

The d are 12-bit unsigned displacements while the b specify the registers with the base address. For each of the operands the actual address is dX plus the value of the bX register. The l is a length field which encodes a length between 1 and 256.

To use more C pseudocode, XC does:

void XC(unsigned char *op1, size_t len, unsigned char *op2)
{
	while (len--) {
		*op1 ^= *op2;
		op1++;
		op2++;
	}
}

(This pseudo code ignores the condition code calculation and exception generation which are not relevant to the discussion.)

This by itself is neat but not every exciting…until you remember that xor can be used to zero out a register. You can use XC to zero out up to 256 bytes of memory. It turns out this idiom is used pretty often in handwritten assembly, and compilers such as gcc even produce such instructions without any special effort on the programmer’s behalf.

For example, in HVF I have this line:

memset(&psw, 0, sizeof(struct psw));

Which GCC helpfully turns into (struct psw is 16 bytes in size):

xc      160(16,%r15),160(%r15)

When I first saw that line in the disassembly of HVF years ago, it blew my mind. It is elegant, fast thanks to the microarchitecture optimizations, and once you are used to the idiom it is clear about what it does. I hope your mind was as blown as mine. Till next time!

dis(1): support for System/370, System/390, and z/Architecture ELF bins

A few months ago, I came to the conclusion that it would be both fun and educational to add a new disassembler backend to libdisasm—the disassembler library in Illumos. Being a mainframe fan, I decided that implementing a System/390 and z/Architecture disassembler would be fun (I’ve done it before in HVF).

At first, I was targetting only the 390 and z/Architecture, but given that the System/370 is a trivial (almost) subset of the 390 (and there is a spec for 370 ELF files!), I ended up including the 370 support as well.

It took a while to get the code written (z/Architecture has so many instructions!) and reviewed, but it finally happened… the commit just landed in the repository.

If you get the latest Illumos bits, you’ll be able to disassemble 370, 390, and z/Architecture binaries with style. For example:

$ dis -F strcmp hvf             
disassembly for hvf

strcmp()
    strcmp:      a7 19 00 00        lghi    %r1,0
    strcmp+0x4:  a7 f4 00 08        j       0x111aec
    strcmp+0x8:  a7 1b 00 01        aghi    %r1,1
    strcmp+0xc:  b9 02 00 55        ltgr    %r5,%r5
    strcmp+0x10: a7 84 00 17        je      0x111b16
    strcmp+0x14: e3 51 20 00 00 90  llgc    %r5,0(%r1,%r2)
    strcmp+0x1a: e3 41 30 00 00 90  llgc    %r4,0(%r1,%r3)
    strcmp+0x20: 18 05              lr      %r0,%r5
    strcmp+0x22: 1b 04              sr      %r0,%r4
    strcmp+0x24: 18 40              lr      %r4,%r0
    strcmp+0x26: a7 41 00 ff        tmll    %r4,255
    strcmp+0x2a: a7 84 ff ef        je      0x111ae0
    strcmp+0x2e: 18 20              lr      %r2,%r0
    strcmp+0x30: 89 20 00 18        sll     %r2,%r0,24(%r0)
    strcmp+0x34: 8a 20 00 18        sra     %r2,%r0,24(%r0)
    strcmp+0x38: b9 14 00 22        lgfr    %r2,%r2
    strcmp+0x3c: 07 fe              br      %r14
    strcmp+0x3e: a7 28 00 00        lhi     %r2,0
    strcmp+0x42: b9 14 00 22        lgfr    %r2,%r2
    strcmp+0x46: 07 fe              br      %r14

I am hoping that this will help document all the places needed to change when adding support for a new ISA to libdisasm.

Happy disassembling!

Happy 50th, System/360

It’s been a while since I blahged about mainframes. Rest assured, I’m still a huge fan, I’m just preoccupied with other things to continuously extoll their virtues.

The reason I’m writing today is because it is the 50th anniversary of the System/360 announcement. Aside from the “50 years already?” sentiment, I have a couple of images to share. (I found these several years ago on someone’s GeoCities site. It’s a good thing I made a mirror :) )

I also came across this video from 1964:

z/VOS - running x86 code on z

Earlier this year, I heard of a company that tried to make a product out of dynamic binary translation of x86 code to Wikipedia article: z/Architecture. Recently, I decided to look at what they do.

The company is called Mantissa Corporation, and their binary translation product is called z/VOS.

Much like VMWARE, they cache the translated code, in z/VOS’s case it’s really a must otherwise I’d guess the cost of traslation would make the result unusable. I like how they used VNC (see the demo mentioned below) to give the virtual x86 box a display.

There is an official blog that has some interesting bits of information. For example, they hint at how they use multiple address spaces to give a the x86 code the illusion of virtual memory. I am not quite sure why they list Wikipedia article: Decimal Floating Point facility as a requirement. Unfortunately, it has been a few months since the last update.

Their website also happens to have a demo of a small x86 assembly operating system starting up and running under z/VOS. I find this fascinating.

LILUG Developer SIG: z/Architecture presentation

I spend the last few days getting ready for tonight’s presentation. It went rather well. It did take a bit longer then I wanted to, but it was still well within the 2 hour-limit.

For those of you who wanted to come, but didn’t get to, here are my slides. I do realize that it glosses over most things, and sometimes hides some rather important details, but hey…I want to see you summarize over 1200 pages of docs in hour and a half :-P

[ANNOUNCE] HVF v0.11

Hello all!

I would like to announce the first public release of HVF — an open source OS for the zArchitecture written in C.

Currently, the OS does very little. It consists of:

- simple process scheduler
- console layer (currently supports only one 3215 device)
- page allocator
- slab allocator (to provide a libc-like malloc())

Once the system is IPLed, it outputs some information to the console, and then continues to idle. While this is not much there is enough code that it lends itself to (aside from my goal with it — see below):

- being used as a basis for experimenting with zArch
- being used as the beginning of a toy OS

Since I do not have access to a zSeries and therefore I had to resort to developing and testing on Hercules. It is possible that there are issues that need fixing to get things running smoothly on the real thing.

The ultimate goal is to have a VM/370-like OS that runs on the zArchtecture - to allow Linux and other modern OSes to run concurrently on a single machine. Here are few of the goals on the TODO list:

- nucleus should be all 64-bit (minus the arch mode switching code)
- mostly in C
- support multiple users
- use SIE to virtualize the hardware (S/390 and zArch modes)
- give something to the mainframe hobbyist community to play with :)

Note that this is all for the hypervisor — I’d like to have a CMS-like OS as well, but that’s secondary. (In a couple of days, I’m actually planning to post a list of ideas for the guest OS to the HVF mailing list — see below.)

You can find the released source code in a tarball at:

https://www.josefsipek.net/projects/hvf/src/

I use Git[1] as the version control system. You can browse the history, as well as obtain the source at:

http://repo.or.cz/w/hvf.git

Feel free to grab a copy of the source code, build it (see Documentation/building.txt in the source tree), IPL it, tweak it, and submit patches :)

I have also set up a mailing list as a place to discuss design, comment on code, etc.:

http://lists.josefsipek.net/listinfo/hvf

Currently, the list gets commit messages whenever something changes in the repository but I’m hoping that once people join it’ll be more interesting :)

Then there is the IRC channel where you can catch me pretty much all the time:

server: irc.oftc.net (the OFTC network)
channel: #hvf

And finally, I have decided to use GPLv2 as the license of choice for the code. The major advantage of doing so is the ability to borrow code (with proper citation of the borrowing) from other GPLv2 projects — namely Linux. The extent of the borrowing is restricted to basic building blocks — e.g., atomic variable types, locking primitives, but not much more beyond that.

Josef ’Jeff’ Sipek.

[1] http://git.or.cz/

Binary Translation is Hard

I spend most of yesterday reading the x86 Intel books, and the equivalent book for the z/Architecture (by IBM). That alone wouldn’t be much out of the ordinary — what I did with the information gathered was fun. I made a sample, proof of concept harness in C that would do “dynamic” binary translation of zArch machine code to x86_64. (I quoted the word “dynamic” because this test program doesn’t execute the code, it just translates what it is given.)

I took the approach of hand assembling the x86 code, which made things a whole lot slower to develop. For instance, I managed to get most of the zArch AR (Add Registers) translating. The original is a 2-byte instruction, and the resulting x86_64 code is about 40 bytes, and I’m still missing a few bits and pieces.

Output from my test program translating AR 5,6:

TRACE, idx = 2, inst = 1, AR
TRACE, R1 == GPR5 == r128
TRACE, R2 == GPR6 == r128
TRACE, about to allocate reg for GPR5, protect r128
Register map:  (z: x86)
GPR:
0: 80  1: 80  2: 80  3: 80  4: 80  5: 80  6: 80  7: 80  
8: 80  9: 80  a: 80  b: 80  c: 80  d: 80  e: 80  f: 80  
TRACE, allocated r8 for GPR5
TRACE, about to allocate reg for GPR6, protect r8
Register map:  (z: x86)
GPR:
0: 80  1: 80  2: 80  3: 80  4: 80  5:  8  6: 80  7: 80  
8: 80  9: 80  a: 80  b: 80  c: 80  d: 80  e: 80  f: 80  
TRACE, allocated r9 for GPR6
TRACE, R1 == GPR5 == r8
TRACE, R2 == GPR6 == r9
TRACE, return 1, 1
block 0x7fffd1e71720
  1 S/3x0 instructions in 2 bytes
  256 bytes for x86 code
  S/3x0 code:
    1a 56 
  x86 code:
    4d 01 c8 49 c7 c7 02 00 00 00 49 c7 c7 00 00 00 
    00 49 c7 c7 03 00 00 00 79 07 49 c7 c7 01 00 00 
    00 49 c1 e7 12 4d 09 fe 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

Powered by blahgd