D
Someone wrote: > Thought it was a double word > As in DS D It is a doubleword, specifically a long (64 bit) floating point type. And yes, DS D and DS 0D are commonly used when floating point is not intended. And as Fortran programmers would know, E is the short (32 bit) floating point type. Now that I think about it, I don’t remember the assembler notation for 128 bit (extended precision) floating point constants, though am pretty sure that it isn’t the Q that IBM and DEC Fortran uses. I suppose I don’t see anything wrong with 0D for doubleword alignment, even when not for floating point data. Probably better not to use D or 2D or others, though. D would be the one that needed doubleword alignment for OS/360, and so its use goes back that far. One could use FL8 for fixed point data, but I suspect without doubleword alignment.
debuggers
Bernd wrote: > We also had a self-written batch debugger, which relied completely on > S0C1 and SPIE to do its instrumentation and implement the breakpoints; > at least in the first version. Reminds me of a debugger I used with Orvyl/370 in S/370 days. I believe it used SVC 255 for breakpoints, which was fine. The when you continue from the breakpoint, it has to somehow execute the instruction at the breakpoint before continuing. I had put a breakpoint on a BR 0 instruction, which was common in the object code from PL/I (F). The debugger branched to the address in register 0. Fortunately, I knew who to contact to fix the bug. No-one had ever tried that before.
S0C1
Shmuel (Seymour J.) Metz wrote: > No; it is guarantied to generate a program 001 interrupt. > You only get an ABEND S0C1 if there is no SPIE/ESPIE exit. I suspect that some use S0C1 as shorthand, and as you note incorrect, description for program interrupt 1.j It might be that some SPIE routines handle the interrupt, maybe print a message, and then allow it through to the OS. I do still remember S0C0 from the 360/91 days, which doesn’t mean program interrupt 0, though the low bits will be . Dreaded by anyone debugging from a hex dump. > I've written code that distinguished[1] between a S/360 and a S/370 > with a SPIE[2] for codes 1 and 2; the exit assumed that it was a S/370 > if the code was 2. I wouldn’t have thought of that one. Pretty neat.
local labels
I believe that some DEC assemblers allow local labels of the form d$ where d is a digit from 0 to 9. Local labels need to be unique between any two normal labels. References to them would, then, only work between those same labels. -- glen
Re: Count Words?
Nothing against discussions on how to write fast code, but I don’t believe that this is normally necessary. About 20 years ago, I was counting words, not just how many, but how many of each word, on gigabytes of text. (Full text US patents for two years.) I did it in Java (with JIT compiler on), and it was plenty fast enough. I did it using the Java StringTokenizer: https://docs.oracle.com/javase/7/docs/api/java/util/StringTokenizer.html which takes a regular expression for the delimiter. Then each word found was either added to a HashTable, or the count for it was incremented. As computers are much faster now, it should be able to do terabytes of text, today. There was one non-obvious thing about the Java code, though. It seems that the way Java normally does substrings is with a reference to the whole character array, which in my case was a line of text. That filled up memory faster than it should have. Using new String() on each word, fixed that problem. (It only does that for the actual entry in the hash table.) But if you do have exabytes of text, then there might be need for assembly speed-up. Well, OK, petabytes are enough. Oh, you might also look at the unix wc command, which counts words. (More specifically, the GNU utilities version, with source available.) About 25 years ago, I compiled the GNU utilities (as they then existed) to run on my OS/2 system. (That is before Linux, and such, that are so convenient today.)
Re: SDWA - SDWACMPC conversion
> Maybe I'm missing something, as this is a bit trickier than the usual > shlop, but wouldn't it be more efficient to OI the last byte of > with x'F0', and skip the MVZ? Using =C'0123...'-C'0' for the TR table of > course. Maybe you are planning to do this a few billion times. Otherwise, do you mean more efficient in execution time, memory used, or time spent coding and debugging? Using the offset translation table requires that the origin is appropriate, such that the displacement isn’t negative. As a general purpose macro, when you can’t be sure where or when it might be used, that could be a problem. In addition, note the trial execution required when the translate table crosses a page boundary. But most likely more time has been spent discussing the efficiency than lost by any inefficiencies in the macro. —glen
tail recursion
Someone wrote: "yes, I Had to do the Same, when I implemented Quicksort in REXX, because the OS/2 Implementation of REXX only supported some 32 nesting Levels." The usual way to write recursive quicksort is to take advantage of tail recursion. Each call will generate two recursive calls for two partitions of the input. One is done with an actual recursive call, and the other, which would normally occur just before return, is done with a branch back to the top. This is tail recursion elimination. If the smaller partition is done with a recursive call, it is guaranteed to be smaller than half the input, so at most log2(N) levels of recursion.
OOP
Someone wrote: "OOP is, I think, quite a bit more than a calling standard - it boils down to an abstracted thought process that you simply cannot do in Assembler. As noted however, you an certainly write a dynamite compiler in HLASM that compiles a OOP language. " You can write OOP in Fortran 66, as I have known it done, and you can also do it in HLASM. Yes it is an abstraction, and yes Fortran 66 and HLASM don't help you so much, but the abstraction itself can be written in pretty much any language. Some languages have protection that stops you from cheating, but you can decide not to cheat. Some have features that help with readability, but again HLASM doesn't.
Re: Fair comparison C vs HLASM
On January 31, 2018 at 8:06 AM Kirk Wolf wrote: On Tue, Jan 30, 2018 at 9:39 PM, Jon Perryman wrote: C is a byte by byte language. Anything not hidden in a primitive or function must be processed byte by byte. In primitives and functions, the compiler can choose how to implement it. The point is C programmers must process byte by byte unless they can find a function. I'm sorry, but can't agree with anything of this. 1) Compilers can generate machine instruction implementations that take advantage of the instructions and architecture available. Even if you write byte-by-byte code, a compiler may rewrite it to use zArch instructions that are not byte-by-byte but equivalent. This is distinctly different from how assemblers work. I think I at least somewhat understand what he means. It occurred to me some time ago, that there is no C library routine to do what MVCIN does. Not that it is hard to do, but there just isn't one. I doubt many compilers compile the appropriate for loop into MVCIN. 2) The "C Standard Library" is part of the C language standard(s). For all of the supposed byte-by-byte C programmers that can't find any functions to use, here are links to the XL/C++ documentation, where the "Runtime Library Reference" can be found: https://www-01.ibm.com/support/docview.wss?uid=swg27036892 The bottom line is that this: memcpy(field1, field2, sizeof(field1)); generates an MVC instruction (or several or a loop or an unrolled loop of MVC instructions). To say that the "C Language" is byte-by-byte is pedantic. It does. But note that C doesn't have some statements that other languages have, that generate a lot of code from a small statement. No array expressions, for example. 3) I also do not agree with your repeated assertion that it means something significant that C was originally developed on a RISC machine ( I believe that it was a PDP-7) with only certain instructions. The RISC/CISC idea didn't come until later. Machines like the PDP-7 have simpler instructions to keep costs down, and make them easier to build. I would have thought that this kind of argument about the relative benefits of assemblers vs compilers (or assembler vs C) would have been over a couple of decades ago. A more current argument is static vs dynamic (VM+JIT) compilation.
Re: Fair comparison C vs HLASM
The 360/20 has MVC and CLC, but, strangely, not LR. (You can use SR and AR instead, so no need for LR.)
Re: Fair comparison C vs HLASM
On January 25, 2018 at 10:57 AM Bernd Oppolzer wrote: (snip) I would like to add: Mainframe ASSEMBLER IMHO is the only Assembler language (or the only instruction set) where humans can write reasonably programs in. All other Assemblers or instruction sets lack the same user friendliness and orthogonality that this platform has from the early days of the 360 system. VAX is pretty human readable, too. That was considered important at the time, though just at the transition away from mostly writing OS in assembler. But yes, RISC assembler programs are not so readable, and also x86 (for any value of x) are not so readable. (snip) BTW: I know of an old PL/1 compiler (Multics), which did the same loop unrolling and outperformed ASSEMBLER programmers this way; my example goes like this: SUM = 0; DO I = 1 to 1; SUM = SUM + I; END; PUT SKIP DATA (SUM); Loop unrolling was a favorite example for the PL/I preprocessor. change to %DO and %END and you have an unrolled loop.
Re: Fair comparison C vs HLASM
(snip on optimizing and compilers) On January 24, 2018 at 8:54 PM Paul Raulerson wrote: Of course, the C compiler took this: #include int main(int argc, char *argv[]) { int c=0; int x=0; for (x=0; x< 1; x++) { c++; } printf ("\nThe final value is [%d]\n", c); } and optimized it during compile time. In fact it optimized it so much it simply generated a LHI of a register with 1 in it. (grin) Needless to say, it ran somewhat faster than my friend’s program. Even counting the screen print. :) ite: http://www.gkc.org.uk/gkc | Erdos number: 4 There is a story from the OS/360 days of a popular Fortran benchmark that evaluated complicated math functions and such, all done using statement functions. It seems that Fortran H expands statement functions inline, and also does constant evaluation at compile time. As in the above example, the compiler evaluated the whole thing at compile time (very slowly) and at run time printed out the precomputed value (fast). If Fortran H could do it 40 years ago, C compilers should do it today. (But I don't know that Fortran H did loop evaluation.) -- glen
Re: Load module
> Yes. My question was "In a called module, how do we determine > if it was called dynamically or statically” The whole design, since OS/360, is that you don’t. If you want to know, pass an argument to the load module that has a different value for the dynamic case. Using LINK, your module is called by the system in pretty much the same way as any other module is called. The only difference is in the arguments, which for statically called (or the first of dynamic) is the PARM string. If another load module calls you, with one argument that is a string after a two byte length, you should work exactly the same way as if you were not called from another load module.
Re: Load module
> Sorry for the confusion caused. I strongly agree this is a basic question > and I too understand the Static, all the loads will be loaded in to main > memory and the load will be placed in to the main memory during execution > time, Dynamic. We can give Call macro and Load macro for the same. My > question was, what are all the possible options where we can say Static / > Dynamic by seeing anything? once again, am sorry for the confusion caused. There may be other explanations, but I usually think about the way the Fortran and PL/I (F) compilers are written. Fortran H uses the usual OS/360 static overlay system, which all goes into one load module. PL/I (F) uses a dynamic overlay, with around 100 load modules with names starting with IEM, and the first being IEMAA. Others have names like IEMAB, IEMAC, etc. So, it isn’t that one load module is dynamic, but the set of 100 all together.
Re: Branch table
> "Tony Harminc" <t...@harminc.com> wrote: (snip) >L R14,R4 (snip) > This sets R14 to the address of the adcon in the entry you just found > in the table (or it would if the above-mentioned boundary alignment > problem wasn't there). You need No, this loads R14 from an address near the beginning of memory. Pretty sneaky calling it R4, but the value is 4, so the result is actually L R14,4 or more precisely L R14,4(0,0) (unless you are on a PDP-10, where the registers are addressable as the first 16 locations in memory). -- glen
Re: local labels
As well as I know it, Macro-11, the assembler for the PDP-11, has local labels with the scope delimited by non-local labels. From: https://en.wikipedia.org/wiki/MACRO-11 .TITLE HELLO WORLD .MCALL .TTYOUT,.EXIT HELLO:: MOV #MSG,R1 ;STARTING ADDRESS OF STRING 1$: MOVB(R1)+,R0 ;FETCH NEXT CHARACTER BEQ DONE ;IF ZERO, EXIT LOOP .TTYOUT ;OTHERWISE PRINT IT BR 1$ ;REPEAT LOOP DONE: .EXIT MSG:.ASCIZ /Hello, world!/ .ENDHELLO The double colon makes an external label, single colon an ordinary non-extern label, and the 1$: is a local label, with scope between the HELLO:: and DONE:. The scope is delimited by ordinary labels, .PSECT, .CSECT, or .ASECT directives, but not equate symbol assignment. More convenient than thinking up dumb names for things that don't really need a name. http://bitsavers.trailing-edge.com/pdf/dec/pdp11/rsx11/RSX11M_V2/DEC-11-OIMRA-A-D_MACRO_75.pdf -- glen
360/20 instruction macros
OK, here are the macros as I use them, with the test for host machine removed. They come from the HRTPB360 program that is part of HASP. Note that OS/360 assemblers support BAS and BASR, possibly for the 360/67. -- glen *** V0082000 TITLE 'H A S P / R T P *MACRO DEFINITIONS*(MODEL 20 INSTS.)' V0083000 * V0084000 * V0115000 * CIO* CONTROL I/O V0116000 * V0117000 MACRO V0118000 NAMECIO A,BV0119000 GBLA MACHINE V012 NAMENULL V0121000 DCX'9B'V0123000 DCAL1(B) V0124000 DCS(A)V0125000 AGO .END V0126000 EJECT V0133000 * V0134000 *DIALS READ MOD 20 DIALSV0135000 * DATA 1,2 IN LOC 252 V0136000 * ADDRESS 1,2,3,4 IN 253-254 DEC V0137000 MACRO V0138000 NAMEDIALS NULLV0139000 NAMEDS0H V014 DCX'83000300' � READ DIALS INTO CORE V01410 00 MEND V0142000 SPACE 4V0143000 * V0144000 * HPR* HALT AND PROCEED V0145000 * V0146000 * V0147000 MACRO V0148000 NAMEHPR NUM V0149000 GBLA MACHINE V015 NAMENULL V0151000 DCX'9900',S(NUM) V0153000 .END MEND V0156000 SPACE 4V0157000 * V0158000 * TIOB * TEST I/O AND BRANCH V0159000 * V016 * V0161000 MACRO V0162000 NAMETIOB A,BV0163000 GBLA MACHINE V0164000 NAMENULL V0165000 DCX'9A'V0167000 DCAL1(B) V0168000 AIF ('A' EQ '*').A2 V0169000 DCS(A)V017 AGO .END V0171000 .A2 ANOP V0172000 DCS(*-2) V0173000 .END MEND V0177000 EJECT V0178000 SPACE 16 V0179000 * V018* XIO* TRANSFER I/O V0181000 * V0182000 * V0183000 MACRO V0184000 NAME
BASR
(someone wrote) I may be wrong but I have the Impression hat the 360/20 version of BAS/BASR (that machine's equivalent to BAL/BALR had a different op code from the current BAS/BASR. I have assembled BAS and BASR with the Tachyon assemmbler with the right X'4D' and X'0D' opcodes. I believe these are from the 360/67. There are some other diagnoses. I believe one jumps to a specified address in microcode, but the useful addresses aren't well documented. More are for the later serial numbers, with microcode in core. -- glen
unusual instructions
The OP said he was working with code for a model 20. That was only barely a true S360 and had a few instructions peculiar to it. Yes. XIO is the I/O instruction that reads or writes. Like other 360's, I/O is asynchronous. You have to test (with TIOB) to see if it is done yet. With 8K core, half the core is available without a base register. As I understand it, many were only 4K. It does have some fairly complex instructions, such as DP, ED, and TR, and leaves out some simple ones like L and LR. Registers are 16 bits, so LH, AH, SH, CH, and STH are there. AR and SR, but not most of the other RR instructions. PACK, UNPK, MVO, ZAP, AP, SP, CP, MP, DP so full decimal arithmetic. MVI, MVN, MVZ, CLI, MVC, CLC, NI, OI, ED, BR, B, BASR, BAS. and then the model 20 specific: XIO, TIOB, HPR, SPSW. -- glen
360/20 instructions
The detail on the instructions are in: httt://www.bitsavers.org/pdf/ibm/360/funcChar/A26-5847-3_360-20_funChar_Apr67.pdf The HRTBP360 program that IBM still distributes, I am told, with HASP, uses macros for the 360/20 specific instructions. (It was written to assembler with OS/360 or OS/VS2 assemblers.) The macros seem to still work with new assemblers. -- glen
absolute addressing, continued
Thanks all for the help with this one. I have known for a long time that the assembler could generate absolute addresses, but never asked why. For those still following, here is the program that reads the object deck: BASR 11,0-2: 0DB0 XIO 78(19,11),80 0: D012B04E0050 BCR 5,11 6: 075B TIOB 8(11),16 8: 9A10B008 TIOB 68(11),1 C: 9A11B044 CLI 78(11),210: 9502B04E BNER 11 14: 077B LH12,84(11) 16: 48C0B054 CLI 80(11),X'D5'1A: 95D5B050 BER 15 1E: 078F CLI 80(11),X'E7'20: 95E7B050 BNER 11 24: 077B LH15,88(11) 26: 48F0B058 AH15,74(11) 2A: 4AF0B04A STH 15,50(11) 2E: 40F0B032 MVC 0(28,12),94(11) 32: D21BC000B05E BASR 15,11 38: 0DFB XIO 76(21,11),1 3A: D014B04C0001 BCR 5,1540: 075F BR12 42: 07FC HPR 2 44: 9902 BR11 48: 07FB DCX'D1FF' 4A: D1FF which runs on a real 360/20, though not, so far, with a real card reader. (Instead, I have an FPGA based virtual card reader.) I didn't write this one, it seems that it is related to HASP, and a program to make a 360/20, or larger 360, into an RJE station. (There is a different loader for other 360's, which I didn't disassemble. For those following such things, the PSW in the 360/20 does have an A bit, and I have run some decimal instructions with it set. -- glen
absolute addressing
(snip, I wrote) I wonder if USING 0,0 and USING 4096,1 should work correctly. What are you trying to accomplish? There are three forms of USING, and all three require an address as the first operand. This is given as a label to tell the assembler that the address of that label is in the register specified. The assembler then computes the displacements for other operands based upon the value that you have told the assembler that you have placed in the register. I have tried it with START 1000, and START 5000, respectively, What do you hope to accomplish with that? This is my first time trying to assemble for absolute addresses. Do you mean that you are not using labels? If so, why? What do you mean by absolute addresses? Do you intend that your program will be loaded into a specific location in memory, determined at assembly time? Yes, it will be loaded into the address specified at assembly. If I say: START 1000 the assembler generates addresses starting from 1000, and the program is loaded into those addresses. In z/Architecture, and dating back to System/370, there are three kinds of addresses: Dating back to S/360, actually... o Virtual addresses. These are the addresses that programs normally work with. o Real addresses. These are the result of Dynamic Address Translation of a virtual address. o Absolute addresses. These are the result of applying the Prefix register to a real address. Well, real addresses also work with DAT off, or on machines that don't have DAT. For actual use with OS/360, this likely only happens in an FLIH, (First Level Interrupt Handler), and the routine that first gets control on IPL, but the assemblers have to be able to do that. Someone from Tachyonsoft has told me the answer, though I am still not sure that I understand it. It goes like: XXX START 1000 USING XXX,0 In the usual case, the displacement is computed by subtracting the desired offset from the offset in the base register, 1000 in this case. But it seems that the assembler instead subtracts zero. I haven't yet tried: USING XXX,0,1 to see if it subtracts 4096, and generates displacements from register 1. -- glen
absolute addressing example doesn't work
In the HLASM release 5 manual, there is an example: If a register is specified with base address zero, the assembler will use it in preference to the default use of register zero. For example: | USING 3,0 | LA 7,5 | generates the instruction X'41703005'; in the absence of | the USING statement, the generated instruction would | be X'4175'. I suppose that works if it said USING 0,3 but what I really want to know how to do is to generate real absolute addresses. I now have an example from Tachyonsoft that looks like: MYCODE START 1000 USING MYCODE,0 LOOP MP X,Y DP X,Z ZAP X,X(13) B LOOP XDC PL16'8000' YDC PL3'8001' ZDC PL3'8000' END LOOP which seems to work. It does generate offsets from zero, instead of from 1000 that it looks like it would. I still don't know why it doesn't subtract 1000 from the displacements. -- glen
USING 0,0
I wonder if USING 0,0 and USING 4096,1 should work correctly. I have tried it with START 1000, and START 5000, respectively, such that addresses are in the appropriate range, but, using the Tachyon assembler, get addressability errors. Or maybe there is an assembler option to allow this that I don't see. This is my first time trying to assemble for absolute addresses. -- glen
Intel Virtualization
As for the ISA, Intel seems to be very ad hoc compared to the z architecture. Especially in the virtualization arena. Basically, the z has a _single_ virtualization instruction: SIE. Intel has I don't know how many different versions of different instructions to let hypervisors run at all. I don't know how efficient vitualization actually is on Intel. But it wouldn't surprise me if it were a pig. As far as I know, the biggest advantage z/ has over Intel (and many others) is the wait state. It is sometimes difficult for virtualization to figure out when the guest isn't doing anything. Most other systems use a null process with a small loop, while waiting for an interrupt. (But if you know you are running virtual, there might be some way around it.) I beleive that the wait state came from the days of usage meters, when the meter would stop while the processor was waiting. If not for rentals of S/360, it might not have had the wait state. -- glen
Re: CE key
Here are pictures of the key switch: https://commons.wikimedia.org/wiki/File:Customer_Engineer_Key_Switch_for_IBM_S-360_computer,_view_1.JPG https://commons.wikimedia.org/wiki/File:Customer_Engineer_Key_Switch_for_IBM_S-360_computer,_view_2.JPG
new instructions (was: LZRG ...)
(snip, someone wrote) And POPCNT is another one. Why do I need to know the number of 1 bits in each individual byte in a GPR? On 2015-03-11, at 08:49, John McKown wrote: Because CDC had it first? I suspect that it became a built-in function in Pascal, CARD(), because Pascal was developed on a CDC which had the hardware. As I understand it, it is used in cryptography. Also, it can be done fast in hardware and isn't that hard if you want to do it. Is POPCNT an inexpensive extension of the Wallace Tree? The ones I know of use a carry save adder tree. I think that is related to the Wallace tree, but I forget the exact way they work. And I suspect FORTRAN's transfer-of-sign, SIGNF() happened because it was a hardware instruction on the 704. I suppose. But now that IEEE cares about negative zero, it has an extra use. Even without the special instruction, it is easy to do with bitwise AND and OR and most hardware. (Though you have to be able to get floating point values in a place where you can do bitwise operations.) -- glen
CE key
I wonder if anyone knows where to find CE keys for S/360 CPUs. thanks, -- glen
Re: CE key
If you're talking about the CE key that switched metering from customer to IBM, I have no idea. Those were a real pin-tumbler lock; not just a simple latch. They may even have been unique to each machine, though I think it would've been impractical to have each CE carry a jangling bunch of them around. I've never seen one on eBay, but then there's precious little S/360 stuff on there of any kind. Yes, that one. I know that DEC used the same key for all the CPUs, and was guessing that IBM did, too. Also, I don't know if it would match the blank that ordinary locksmiths would sell. thanks, -- glen
Decimal intructions, was: Redesigning POps.
Gary wrote: I have heard that only one machine was ever delivered without the decimal set, but it may have just been rumour. All the 360/91's were delivered without the decimal instructions. The OS emulates them when the illegal instruction exception is generated. But maybe you meant only on machines where decimal was in option. The 360/20 has the decimal instructions except for SRP, but not most of the binary instructions. (It has MP and DP but not M, MR, D, or DR.) Without having ever looked at it, I presume that RPG does mostly decimal arithmetic, other than address calculations. -- glen
Reference summary for 360/20
The mention of instruction sets and green cards reminds me, does anyone have a (scan of) a 360/20 Reference Summary? Some places indicate that it might be yellow or red. -- glen
Trial execution
Someone wrote: The problem with TRT is it validates the whole TRT table before it starts to do the TRT. As far as I know, TR, but not TRT, can do a trial execution. First, it is only needed if the translate table starts within 256 bytes before a page boundary. But it is needed for TR, as TR modifies the first argument before it knows the extent (on both sides of the boundary) of the second argument. TRT does not modify its argument, and so doesn't have that problem. It might be also for ED and EDMK, though I have never used either. The other SS instructions know the extent of both operands before any data is modified, and can generate the page fault interrupt at that time. -- glen
architecture book
My favorite book describing the variety of computer architectures is the Blaauw Brooks book. Many of the examples have a little more detail for S/360 and S/370, but they have all of the important details for many other older and newer systems. Otherwise, the previously mentioned book seems to be available in the paperback international version for a lower price, and used in the hardback not so much more. -- glen
Re: OT: SI units and precision
Someone wrote: At least that explains I don't need to worry that km is not suddenly 1024m as soon as I carry a storage device ;-) Reminds me that I used to wonder if IBM sold computers in units of $1024, that is, k$. I presume everyone here knows that the serial numbers on S/370 CPUs are in hex. -- glen
Re: Why is division by zero permitted?
From C28-6514-5 on bitsavers, on page 16: Division by zero is permitted and yields a zero result. After that, (and presumably also earlier) it has to stay that way as code (macros) might depend on that. There is no reason given. -- glen
Re: handling a remainder form a DP
My result from a DP in dividing 1300 by 3 is 00 00 00 43 3C 00 1C but on a calculator it is displayed as 433.3 - which is what I want to display in a field on a screen. How do I turn that remainder of 1C into the decimal value ? You should have enough to do it as scaled decimal. Consider the dividend as 1300., divide by 3 and you get 433. ( and remainder 0.0001) Multiply the dividend by 1 (probably with SRP) then do the divide, and the quotient will have four digits after the decimal point. Print at appropriately. If you don't have enough digits to do that, you can convert the already computed remainder by muliplying it by 1 (SRP) and then dividing it by the original divisor, 3, to get remainder 1. That is, considering the shift, 0. remainder 0.0001. -- glen
Re: Instruction Lists/Counts.
Instructions are hard to count, though instruction count isn't a very good way to determine CISCness. RISC tends to have a small number of instruction lengths, often 1. S/360 through z/ have three lengths. Not too CISCy, but not RISC. (VAX might have 14 or so, from one byte on up.) RISC tends to minimize address modes. Some have been added lately, but the largest fraction of instructions executed should still be RR or RX. Not too CISCy, but not so RISCy, either. VAX has many address modes, 21 on the list that I have, but 14 of those also have an indexed mode, so it should be 35. And there can be more than one such address per instruction. (Many operands are register only, but I am pretty sure that there are some where two operands can have one of those 35.) Many RISC systems try to execute every instruction in one cycle. That brought things like MULTIPLY_STEP, an instruction that did part of a multiply, but that had to be executed many times to do an actual multiply. Most try to avoid this now. There are some pretty complicated instructions even from S/360, and many complicated ones added later, which are pretty CISCy. Still, in terms of instruction length and address modes, not so bad. Since S/360 through z/ use different opcodes for different addressing modes of the same instruction, do you count those as separate instructions, or just one? (Compare to VAX, where there is an opcode byte and address mode byte.) -- glen
Re: OPSYN self execution
Jonathan Scott wrote: If you want to modify DC, you need to define an opcode which refers to the original DC first so that you can invoke it from within the macro. DC_ OPSYN DC Set up alias for original DC DC OPSYN MYDCRedirect DC to my macro Then within the macro you can use DC_ whatever Issue real DC But John Ehrman's method is neater, as it doesn't require a special OPSYN from the outside. Some one could directly call MYDC, or use OPSYN, either way it would work. I have never used OPSYN, but I have written postscript programs that redefined the \def operator. Now, what happens if OPSYN is OPSYNed? -- glen
more than one base register
Someone wrote: MYCSECT CSECT USING *,R15 B BYID ID DCC'module-name' BASESDCA(MYCSECT) DCA(MYCSECT+4096) DCA(MYCSECT+2*4096) DCA(MYCSECT+3*4096) BYID DS0H LMR9,R12,BASES DROP R15 USING MYCSECT,R9,R10,R11,R12 This looks more like compiler generated code than what I would expect from a person. Then again, my start on learning assembler was reading the LIST output from the compilers. When I saw the 4095 in the subject, I was expecting the old: L 12,4095(15) L 11,4095(12) L 10,4095(11) USING MYCSECT,15 USING MYCSECT+4095,12 USING MYCSECT+2*4095,11 USING MYCSECT+3*4095,10 The LM form seems to waste fewer bytes loading the base registers (including the A constants), especially if one already has the branch around the csect name. But, why the DS 0H instead of putting the label on the LM? -- glen
DS 0H
(snip, I wrote) But, why the DS 0H instead of putting the label on the LM? I do the same thing for labels to code. Why? Hum, I guess from reading the HASP code long ago. Also, it makes it easier to insert a new instruction at that logical point in the program without remembering to remove the label from the old instruction and move it to the new one. That I don't disagree with, but what is the probability of wanted to add new code between the B and the LM? I suppose one still has over 4000 bytes of code (not counting data references) before one needs the next base register, but, really, what else would you want to do there? Now that I write that, where is the STM 14,12,12(13)? Still, that isn't the kind of change I would plan ahead for. At the time, I was considering differences between compiler generated and human generated code. I suppose that one isn't a very good test, though. In addition, if you use SUPERC to compare the two sources (before after), then the old instruction does not show up an a delete and add. Only the new inst ruction shows up as an add. Remember the days of IEBUPDTE to update source. Fewer updated cards means fewer mistakes. Oh, yes, in the general case I agree. It just seemed unneeded in this specific case. -- glen
bit masking
I am working with some IPv6 addresses that are 128 bits long. The input to the program is an ip name or address and the number of high bits that I need to use for a compare against another ip address. So, I want to create run time routine to build the a 16 byte 'and' bit field based on the input number of bits. (I will then 'and' both addresses and then use a simple CLC.) There is no double 64 bit (that is, 128 bit) shift instruction as far as I know. Most obvious is to store the bits in some number of bytes, halfwords, words, or doublewords. Then, based on the shift amount, fill some with all ones, and use a shift instruction (or smaller table) for the boundary case. I would probably choose words. Using shift and mask, split the shift amount into 32's and a remainder (or use Divide). For bytes in memory, EX an MVC, or a loop of MVI, to fill the high bytes. Use a table of bytes to IC and STC the boundary byte. -- glen
Re: MNEMONICS
(someone wrote) IHMO, the mnemonic for BCT was not well-chosen. Better might have been DBZ for Decrement and Branch on Zero. That would be Decrement and Branch on Not Zero, DBNZ, and also DBNZR. Sounds too much like DEC to me.(*) I believe none of the S/360 instructions are more than four letters long, though. As for the below case of BALR, clearly, there needed to be yet another instruction :- (*) I was doing S/370 assembly programming for a few years before I first programmed a DEC system, a PDP-10 running TOPS-10. The DEC mnemonics are a little different, but the decrement and skip/jump are usual. Note that on the PDP-10, the JUMP instruction doesn't jump, the JUMPA instruction actually does, but usually JRST is used instead. -- glen
Underscore character
(snip, someone wrote) You've sometimes admonished me for taking the synchronic view rather than the diachronic. But here, you're being narrowly synchronic. In the Bad Old Days of Yore, mechanical serial printers could be commanded to underscore with the sequence underscorebackspacecharacter-to-be-underscored. In this diachronic perspective, underscore is not a misnomer, merely antiquated. No, you write a second line with a '+' as carriage control character. This is even so popular as to be a special case for the 3800, which otherwise does not allow writing two characters on one print column. Presumably it builds a record in a buffer, allowing overprint with different fonts, and a special bit to indicate underlining. With ink and ribbon printers, you can get darker print (bold-like) by overprinting the same characters using '+', though I believe that the 3800 also doesn't do that. -- glen
Re: FORTRAN II functions
(snip, someone wrote) o IBM hexadecimal floating-point, HFP, o ANSI binary floating-point, BFP, and o ANSI decimal floating-point, DFP. Of these the first two, HFP and BFP, make zeros positive; but the third, DFP, supports both positive and negative zeros. The change to the Fortran standard comes, I believe, from support for IEEE binary floating point, which is what went into IBM's BFP. Among others, the reciprocal of -Infinity is supposed to be negative zero. DFP, from the new IEEE standard, should also include all the negative zero properties of the old standard. (snip, someone else wrote) What is x'8000 ' interpreted as HFP? I do remember that LNER and LCER generate negative zero, but I am not sure about some other cases. How about: X=-1e73 Y=1e-10/X with exponent underflow mask bit off? In any case, in all three (HFP, BFP, and DFP) negative zero and positive zero compare as equal. It is only with tests like SIGN(X) in Fortran that you can detect negative zero. Many years ago, I learned that the CALL/OS Fortran compiler (or, more likely, library) would print +0.0 if given a negative zero. No sign was printed for positive zero. -- glen
Fortran II functions
Finally, ISTR, but can find no references, that FORTRAN II had a two argument SGNF(X,Y) defined as the magnitude of X with the sign of Y. A plausible motivation is this was a single machine instruction on the IBM 70x series -- doubleword shift with a count of zero. The SIGN function is still in Fortran, along with the more specific functions ISIGN and DSIGN (for integer and double precision). (Fortran II function names had to end in F, a restriction removed for Fortran IV and the ANSI Fortran 66 version.) (Newer standards include the effect when X is zero on machines supporting a negative floating point zero.) The arithmetic IF is still in Fortran, though its use is discourage and it is, I believe, on the obsolescence list. -- glen
calling convention
(someone wrote) My understanding is that the C standard calls for all parameters to be passed by value. My experience is that IBM's C usually passes parameters by reference except that if a parameter is a pointer it gets passed by value. Go figger. That is most consistent with the way it was traditionally done. The requirement is for as if to work. It should be possible to pass the addresses and the callee makes a local copy, or pass addresses of copies. The OS/360 Fortran compilers (G and H) make local copies of scalar variables, and then copy them back before return. (Usually described as call by value result.) That is legal Fortran. For a Fortran call, local variables will have compile time (relocatable) address constants, but dummy arguments arrays will use the address passed in with the call. PL/I passes the address of a temporary variable for expression arguments, or arguments known to have different attributes. To be most consistent with the OS/360 calling conventions, as a series of A-type address constants, the last with the high bit set, one would either pass addresses of copies, or expect the called routine to make copies. That would allow for calls between C and other languages. -- glen
Re: EDIT instruction
(previously I wrote) The book Computer Architecture: Concepts and Evolution by Blaauw and Brooks has many descriptions on how instructions got to be the way they did. (Blaauw was the main designer of S/360... I thought that Gene Amdahl was the principle architect of 360. A search to check my facts seems to reveal that Amdahl, Blaauw and Brooks led the design team. I don't know the actual hierarchy, but yes it was those three. My feeling was that Blaauw made the higher level decisions (should we have an EDIT instruction) and Amdahl the lower level decisions (can we really implement this, how many digits can it do, etc.) Both are pretty important. Brooks, at least as described in Mythical Man Month, led the OS/360 project. In the above mentioned book Blaauw takes the blames for what he considers his mistake in adding the EDIT instruction. As to programming, microcode is now usually considered firmware, though the term is likely more recent than S/360. The microcode of most S/360 models was actually hardware, physical capacitors or transformers. The floppy disk was origially meant to load the microcode store in S/370 models, replacing the hardware microcode storage. More recently, hardware is designed in verilog or VHDL, hardware descriptor languages. Logic gates can be written out as easily as software. As the cost of masks has increased, hardware is more often done through programmable logic where bits activate gates on a chip. Even more, there are system that allow for dynamic reconfiguration, the hardware equivalent of self-modifying code! -- glen
Instruction selection
Someone wrote: Should we have machine instructions to compute a polynome of grade n? I don't think so (but there were machines in the 60s which did just that, and - in that period - they were faster by using such instructions). VAX had polynomial evaluation in the 1980's, and it was well known to be slower than doing it with separate instructions. For that reason, it was likely rarely used, even if it got faster in later versions. The VAX instruction for doing subscript calculations, including bounds checking, was also known to be slower than doing the same thing without the special instruction. RISC or CISC, if some operation is done often enough it makes sense to have a special instruction. As Blaauw did much of the design of the S/360 architecture, in many cases he is criticizing himself. It would be rare for ED or EDMK to be used enough in a program to make a significant contribution to the CPU usage. (Most likely even in 1963.) Decisions that make sense one year might not the next. The S/360 instructions have done well over the years. -- glen
Re: CDS and alignment question
It is the address in memory that matters. This reminds me of programs with two base registers, using LA to set the registers such that the offset of the second is 4095 from the first. All instruction addresses (an branch instructions) will then have an odd offset, legal but it looks funny. On the other hand, consider all the wasted bits in even offset branch instructions. -- glen