CS4:COMP LN3 A COMPILER WRITERS VIEW OF THE IBM 370 The IBM 370 is a byte-addressed general register machine which is a minor improvement of the IBM 360 series designed in the late 1950's. The order code is mostly orthogonal and consistent but the addressing still reflects the 1950's view that 64Kb was a large main store. Operations are provided on: bytes or characters 8 bit unsigned halfwords 16 bit signed words 32 bit signed short floating 32 bits long floating 64 bits A small amount of support is provided for 64-bit integers and 128-bit floating operations but these are not relevant to ALGOL and will be ignored. All addresses are in bytes. Multi-byte items having a byte address "B" occupy bytes "B", "B+1" .... "B+n-1". Byte "B" is at the most significant end of the integer or floating number. Multibyte items can be on any boundary but there are substantial penalties for misalignment. Words and short floating numbers should be on 4-byte boundary, long floating numbers on an 8-byte boundary, e.g. -------------------------------------------------- long floating| | -------------------------------------------------- words | | | -------------------------------------------------- halfs | | | | | -------------------------------------------------- bytes | | | | | | | | | -------------------------------------------------- B B+1 B+2 B+3 B+4 B+5 B+6 B+7 B+8 Data Formats ------------ Integers are stored in normal two's complement form but reals are in hexadecimal floating point form. ------------------------------------------------------- |S| Exponent | Mantissa | ------------------------------------------------------- Bits 0 1 7 31 or 63 The most significant bit is a sign bit and this is followed by a 7-bit exponent; the remaining 24 or 56 bits are the mantissa. The exponent is biased by 64 (X'40') and the mantissa is in the range of 1>M>=1/16. Thus:- X'41100000' is 1/16 * 16^(65-64) = 1.0 and X'C0800000' is -(8/16) * 16^(64-64) = -0.5 A floating number is normalised if the top quartet of mantissa is non-zero; arithmetic operations normally finish by normalising the number. This involves left shifting the mantissa by four bits and subtracting one from the exponent - this process is repeated as necessary. If the exponent goes <0 then floating underflow has occurred - if it goes >127 then floating overflow has occurred - these occur at about 10^(-75) and 10^(77) respectively. An eccentricity of IBM is the significance error. If you subtract 1 from 1 you are left with X'41000000' which won't normalise, and the significance error interrupt occurs. This can be masked, whereupon the result is set to true zero i.e. all bits zero. The first action of any Algol program should be to mask significance error and underflow. There is also a packed decimal data format which is not required by Algol. Base & Displacement Addressing ------------------------------ When an instruction has to address memory it contains a base and displacement or DB field of 16 bits. The top 4 contain a general register and the lower 12 a displacement. The displacement is added to the contents of the register to give a store address and the implicitly sized operand is picked up. In some instructions - notably the branch and shift instructions - the address itself is the operand. When GR0 is the base it yields zero not its contents. 12 bits allows a maximum of 4095 bytes or 1023 words. If the displacement is greater than this, the register has to be copied and incremented using a table of multiples of 4096 and then the new base used. Your compiler will have to check all DB addresses it generates for this displacement overflow problem. Most arithmetic instructions have a base index and displacement address, or DXB field, which takes 20 bits. The first 4 bits have an index register and the lower 16 are a DB address as above. The indexed address is formed by adding the base and index registers and the displacement; there is no implied scaling of the index. Dealing with displacement overflow is easier if the index register is unused. (Even if it is used, the LOAD ADDRESS instruction can be used to combine index and base.) A multiple of 4096 can then be used as an index. PSW and Registers ----------------- A program state on the IBM is defined by a Program Status Word (PSW), 16 general registers and 4 floating point registers of 64 bits annoyingly numbered 0, 2, 4 & 6. Each floating point register can also operate in 32-bit mode. The program status word is a 64-bit integer of which the bottom 31 bits (24 bits in the earlier 360 series) has the address of the next instruction. The only other parts of interest to the non-privileged user are the condition code in bits 18 & 19 and the program mask bits 20-23. Both these can be set by the SPM (set program mask) instruction q.v. The condition code is normally set by most instructions as follows:- CC = 0 result is zero = 1 result is less than zero = 2 result is greater than zero CC = 3 result has overflowed Instruction Formats ------------------- Each IBM opcode occupies one byte and the instructions occupy one, two or three half words. The length and basic format of the instructions can be deduced from the top 2 bits of the opcode as follows:- Top 2 bits Range Format Size ---------- ----- ------ ---- 00 X00 - X3F RR 2 bytes 01 X40 - X7F RX 4 bytes 10 X80 - XBF RS or SI 4 bytes 11 XC0 - XFF SS 6 bytes The above 5 forms cover all the instructions of the 360 and all the common ones on the 370. However, in extending the operations IBM ran out of opcodes in the RR and RS areas and invented new formats RRE, SSE and S; none of these instructions are necessary for the course. The 370 is a 2-address machine; most operations, eg. ADD, take place between two operands and the result overwrites the first leaving the second unchanged (Op1#Op2). The RR instructions are between two operands in registers and have the format - _________________________ ! ! ! ! ! OP ! R1 ! R2 ! !_______!_______!_______! 0 8 12 The RX format is the most useful to compiler writers - ____________________________________________ ! ! ! ! ! ! ! OP ! R1 ! R3 ! R2 ! D2 ! !________!_____!_____!_____!_______________! 0 8 12 16 20 This is a two operand instruction where the second operand is in store at ((R2)+(R3)+(D2)). R3 is the index which is added to the normal base and displacement address. The form enables array elements to be used directly from store. Almost all RX instructions have a corresponding RR version with an opcode X'40' less and a mnemonic with a final "R". e.g. A X'5A' and AR X'1A' normally called Add and Add Register. The RS format is the same as RX but interpreted differently. R3 does not index the second operand but is a third operand in a register. Apart from the shift instructions in which R3 must be zero the only relevant operations are LM and STM for loading and storing groups of registers. The SI format is:- ________________________________________ ! ! ! ! ! ! OP ! I2 ! R1 ! D1 ! !________!________!_____!______________! 0 8 16 20 I2 is an 8-bit unsigned immediate operand - the first operand is in store at ((R1)+D1). The TM instruction enables an Algol program to test a Boolean without loading it into a register. The SS instruction format is - _______________________________________________________ ! ! ! ! ! ! ! ! OP ! L ! R1 ! D1 ! R2 ! D2 ! !_______!________!_____!____________!____!____________! 0 8 16 20 32 36 The operation takes place between two in-store operands of length L+1 bytes. The first operand is normally overwritten. Only Move (MVC) and Compare Logical (CLC) are relevant. The three new formats are of little relevance. Branching on IBM Machines ------------------------- IBM machines have a 2-bit condition code which is set by most instructions but not by LOADS, STORES or MOVES. A family of compare instructions are also available which just set the condition code. A Branch instruction has a mask e.g. BC 7, LAB The mask occupies the R1 field of instruction and is 4 bits. The first bit - bit 0 means branch at CC=0 second bit - bit 1 means branch at CC=1 third bit - bit 2 means branch at CC=2 fourth bit - bit 3 means branch at CC=3 Thus BC 7,Lab means branch on CC=1, 2, 3, but not on CC=0. BC 15 always branches and BC 0 never branches and is the normal "NO-OP". The problem is that LAB is a base and displacement address - how should the compiler provide the base especially for forward references. The general solution is to have GR12 holding the address of the start of the program and also pointing to a table of multiples of 4096. The compiler must generate sufficient of these before generating any code. A branch is thus two instructions - loading a multiple of 4096 into a free general register and then using the DXB format of the BC instruction. The PUT interface does this for the compiler - all it needs is a work register in which to put the multiple of 4K. For procedure linkage the BAS instruction is used; here the R1 operand is a general register which receives the address of the NEXT instruction. The target address is similar to the BC instruction. For loop control there are 3 specialised instructions, BCT (RX) BXH and BXLE (RS). The two latter are difficult to use within the PUT system as they do not have an index register in the instruction. The generality of the Algol "for" is such that BC is generally required. Note that the return address set by BAS acts as a "Base" for branch instructions for the following 4096 bytes of code; indeed a special variant :- BASR R1,0 can be used to set a base register without branching. The PUT routines PUSING and PDROP enable PUT to note such secondary base registers which can be used, if appropiate, when filling in the jumps. No mention of branching on IBM machines is complete without a mention of the Execute (EX) instruction. This RX instruction expects to find another instruction at the second operand address, which is obeyed. The effect is exactly as if the target instruction had overwritten the EX. If the first operand of EX is R0 then the target instruction is executed unchanged. Otherwise, the bottom 8 bits of the register specified by the first operand is ORed into the target instruction before it is obeyed. This was designed to enable lengths to be supplied for SS instructions at run time without modifying the code. Many interesting effects can be obtained by using EX - among them are optimising simple variables passed by name. Programming Tricks and Efficiency --------------------------------- A safe rule on 370 is that it will take less time to execute fewer instructions - there is only one common exception. One or two tricks are useful. 1. The fastest way to get a zero register is to use SLR to subtract it from itself. 2. The LA (load addres) when used with base and index of zero will put 0-4095 into a register as a load literal. 3. BCTR Rn,0 will subtract one from general register Rn faster than any other method. Facienda -------- 1. Study the attached sections of "PoOPs". 2. There are no fix and float instructions on IBM and no transfers from general to floating registers. Try to work out FLOAT and FIX sequences. 3. In Algol a condition can be assigned to a Boolean i.e. Bool:=i