RxRandom Revisited — Metal C

By | October 6, 2013

Continuing the Writing a Rexx Function in C and the follow-on Updated RxRandom External Rexx Function (in C) discussion, can I convert RxRandom to Metal C? I originally worked on writing Rexx external function in C using the System Programmer C facility; this was before Metal C existed. There should be some performance benefit to using Metal C, I think. The resulting load module should be a lot smaller, anyway. Let’s try it and see.

The Metal C environment severely limits the runtime library support, there just aren’t as many functions available, but I should have what I need for this.

Things to change from the previous RxRandom.c source.

  • Remove the include for spc.h since we aren’t using SPC any more.
  • Add includes for builtins.h and stdio.h. I probably should have had these before but the compiler handled it for me then. Now, without stdio.h, for example, you see a bunch of missing __SSCANF references.
  • Replace the access to Register 0 using __xregs(0) with something else since _xregs() is part of SPC. I replaced
    envblockp = (struct envblock *) __xregs(0);

    with

    __asm ( " L 15,4(,13)\n L 15,20(,15)\n ST 15,%0\n"
      : "=m"(envblockp)  
      :
      : "r15" );

    to fetch Register 0 from the chained save area and store it in envblockp.

  • After much trial and error fiddling with the __asm constraints, I settled on this to replace the call to EDCXABND with an invocation of the ABEND macro:
    if (rc > 0) { 
      __asm ( " ABEND (%0),REASON=(%1)\n"        
        :                                        
        : "XL:NR:r1"(rc + 3000), "XL:NR:r15"(rsn)
        : "r14", "r15", "r0", "r1");                                
    }

    This instructs the compiler to generate code to put the abend code into R1 and the reason code into R15, which is where the ABEND macro is going to put them anyway. The options on the __asm statement are documented here.

Surprisingly little had to change in the source code. I had a little more trouble getting the compile to work.

  • Add the “METAL” compiler option.
  • Fiddle around with SYSLIB and the SEARCH option so that the path /usr/include/metal/ is searched first. This took a lot of trial and error for some reason //CEE.SCEEH.+ kept coming up first. I ended up putting the three locations I needed in the SEARCH parameter after coding an additional NOSEARCH parameter. Ugh. If you get errors like this:
    ERROR CCN3205 CEE.SCEEH.H(STDDEF):26    Language Environment standard C headers
    cannot be used when METAL option is used.

    This is probably the problem.

  • Took out the Pre-link/Link step, EDCPL, and replaced it with ASMACL to assemble the output from the C compiler (which the EDCC PROC put in &&LOADSET) and do the link edit.
  • I got some undefined opcode errors trying to assemble the program because our HLASM is not configured to use the most current opcode table. Probably if I had used a lower ARCH() value compiler option, I wouldn’t have had this problem. In any case, I added PARM.C='OPTABLE(ZS6)' to bring the assembler up to speed.

So, this is what I ended up with:

// JCLLIB ORDER=(CBC.SCCNPRC,ASM.SASMSAM1)
//*
//CC        EXEC EDCC,
// INFILE='XXXXXXX.SRC.C(RXMETAL)',
// CPARM='OPTFILE(DD:CCOPTS)'
//COMPILE.CCOPTS DD *
METAL
LIST
SOURCE
NOMARGIN
NOSEQUENCE
OPT(3)
ARCH(10)
TUNE(10)
LOCALE
NOSEARCH
SEARCH(/usr/include/metal/,//'SYS1.SIEAHDR.H',//'XXXXXXX.SRC.H')
//*
//ASMACL       EXEC ASMACL,
// PARM.C='OPTABLE(ZS6)',
// PARM.L='MAP,LET,LIST,RENT,REUS'
//C.SYSIN      DD DSN=&&LOADSET,DISP=(OLD,PASS)
//L.SYSLIB     DD DISP=SHR,DSN=CSF.SCSFMOD0
//L.SYSLMOD    DD DISP=SHR,DSN=XXXXXXX.SRC.LOAD(RXMETAL)
//L.SYSIN      DD *
 ENTRY RXRANDOM
 NAME RXMETAL(R)

As before the Rexx headers were built from the Rexx macros in SYS1.MACLIB using the EDCDSECT utility and put in XXXXXXX.SRC.H. See the earlier post for this information. SYS1.SIEAHDR.H has the headers for ICSF, csfbext.h in this case and CSF.SCSFMOD0 has CSNBRNG for the link-edit.

The resulting load module on my system is only 1,480 bytes compared to the SPC version’s length of 20,864. 520 bytes of that is the CSNBRNG routine linked in. This is quite a nice savings.

Reviewing the assembler listing is quite instructive for learning the newer opcodes and 64 bit instructions.

Here’s the new source: rxmetal.c

Thanks to Kendrick Wong & Peter Relson for some useful SHARE presentations on Metal C.

I think I like Metal C!

Leave a Reply

Your email address will not be published. Required fields are marked *