s390guy / SATK

Toolkit for creating baremetal programs targeting mainframe compatible systems
GNU General Public License v3.0
41 stars 6 forks source link

**HOT!** Incorrect "RIL(a)" instruction format processing (e.g. `LGFI` instruction) #40

Closed Fish-Git closed 3 weeks ago

Fish-Git commented 3 weeks ago

I am trying to compile via ASMA a simple test program (that will eventually become part of SDL Hyperion's test suite) that one of our fellow developers (Jürgen Winkelmann) wrote that ASMA is complaining about:

000002C6  D53F 0800 0600      00000800  00000600    75          CLC   FO(64),PBNULL  first 64 bytes zero ..
000002CC  4770 02D2                     000002D2    76          BNE   *+6            .. is not plausible
000002D0  0000                                      77          DC    H'0'           disabled wait DEAD if first 64 bytes zero

000002D2  0000 0000 0000                            78          LGFI  R3,FO+65536-63 last 64 bytes ..
          ** [78] operand 2 must not be an address (error=0x200): ABS:0x107C1

000002D8  D53F 3000 0600      00000000  00000600    79          CLC   0(64,R3),PBNULL .. zero ..
000002DE  4770 02E4                     000002E4    80          BNE   *+6            .. is not plausible
000002E2  0000                                      81          DC    H'0'           disabled wait DEAD if last 64 bytes zero

The FO ("First Operand") argument (which is actually the LGFI instruction's 2nd operand of course! Duh!) just so happens in this particular case to be a field at at a specific location in memory:

00000788                      00000788  00000800   133          ORG   PRNOTEST+X'800'
00000800                                           134 FO       DS    0X             first operand

which is used in several other places in the program as a target/destination field, as one would normally expect. In this particular case however, it is being used as a term in a numerical calculation whose resulting end value ASMA is incorrectly complaining "can't be an address".

The question is WHY?

Why can't it be an address?

As far as the instruction is concerned, it's just a freaking number. Who gives a rat's ass how it is calculated?

I believe the fact that the defined RILA format in the "...\asma\msl\formats.msl" file incorrectly defines operand-2 of the "RILA" instruction format as being a "RI2" (Relative Immediate) type operand (instead of just an "I2" Immediate) type operand, may have something to do with the problem. (Maybe?)

  (formats.msl):

#     0     4     8     12    16    20    24    28    32    36    40    44   47
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#     |     OP    | R1  | XOP |                      RI2                      |
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#
# RILA: MNEMONIC R1,RI2
#
format RILA
    length 6
    xopcode 12 15
    mach R1 8 11
    mach RI2 16 47 signed
    source R1 R1
    source RI2 RI2

#     0     4     8     12    16    20    24    28    32    36    40    44   47
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#     |     OP    | R1  | XOP |                     RELI2                     |
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#
# RILB: MNEMONIC R1,RELI2
#
format RILB
    length 6
    xopcode 12 15
    mach R1 8 11
    mach RELI2 16 47 signed
    source R1 R1
    source RELI2 RELI2

#     0     4     8     12    16    20    24    28    32    36    40    44   47
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#     |     OP    | M1  | XOP |                     RELI2                     |
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#
# RILC: MNEMONIC M1,RELI2
#
format RILC
    length 6
    xopcode 12 15
    mach M1 8 11
    mach RELI2 16 47 signed
    source M1 M1
    source RELI2 RELI2

#     0     4     8     12    16    20    24    28    32    36    40    44   47
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#     |     OP    | R1  | XOP |                      RI2                      |
#     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
#
# RILD: MNEMONIC R1,RI2
#
format RILD
    length 6
    xopcode 12 15
    mach R1 8 11
    mach RI2 16 47
    source R1 R1
    source RI2 RI2

  (Principles of Operation): RIL(a)-format

Unfortunately though, when I update the formats.msl file with the corrected values (by replacing "RI2" with just "I2") the problem still occurs. And trying to chase the text of the error message itself doesn't help me to locate where the error/bug may be hiding either. (*)

So I need some help!   (Please?)

This is something that is currently holding up the current release, and I'm unable to fix it or work around it myself.

Thanks.

p.s. Not that is matters, but Jürgen built his test using z/OS's assembler, which of course does not complain at all. Now I know ASMA wasn't meant to, and never claimed to, be compatible with IBM's assembler. I know that. I mention it soley to illustrate that syntactically there is nothing wrong with the way the instruction is coded. It is completely legal for operand-2 to be a storage address or any other numerical value. It's just a signed number, no matter how it is calculated, but it's currently being incorrectly treated as a relative immediate value instead of just a signed binary immediate value.

Attached is the failing source file and listing.

I thank you in advance for any expedited attention you can give to this issue.


(*) I'm not trying to tell you how to write your own software, Harold! You know that! I'm just making a simple suggestion, that's all. It would be nice if you could somehow assign a unique message number to each place where an error message is issued. Maybe a combination of an abbreviation of the source module's name where the error was detected/thrown in combination to a module-unique number? Or better yet, the exact source file location? (name and line number?) I don't know if that's possible to do in Python or not, but something to make your code easier to debug for we mere mortals who didn't create (write) your most excellent and much appreciated product!  :)

s390guy commented 3 weeks ago

So, as the error indicates, ASMA, is NOT treating an address as simply a number. Your assumption is not correct. Addresses are not just numbers in ASMA. Working As Designed.

Yes, I get you do not like the design.

The source of the error is how addresses are handled within ASMA for the purpose of calculations. Addresses are tagged as "addresses" and the attribute remains with the result of calculations that adjusts the address (+ or -). So F0+65536-63 still has the "address" tag.

The instruction formats require, integers. So the LGFI instruction must use an integer not an "address".

The only way to remove the "address" attribute is to subtract from F0 another address to create an integer, or in this case simply use the integer X'800'. I am assuming you want to make the code flexible enough to change the position of F0 in the future.

As a solution, I would suggest that you create somewhere in the code a symbol equated to an integer, like this:

When you define F0 use code it like this

F0DISP EQU X'800' ORG PRNOTEST+F0DISP F0 DS 0X

And in the LGFI instruction, use F0DISP instead of F0. Continue to use F0 in the rest of the program when an instruction uses an actual address. If you need to change where F0 is actually placed , adjust the F0DISP equate.

I did not test this, but I believe it will solve the immediate problem. Feel free to use as many expletives as you like if it makes you feel better when the explain why you are doing this. LOL

Harold

s390guy commented 3 weeks ago

I wanted to send off a "work around" as quickly as I could and hope it works. As I said I did not test it with your code. And, I would encourage you to reset your MSL file definition for LGFI. The instruction format definition is not the problem.

For a fuller explanation of the implications of this design and why it exists...

As mentioned, legacy assemblers treat an address as an integer. And that is where ASMA departs from the legacy assemblers, such as z/OS.

ASMA associates at all times an address with two pieces of information, the CSECT in which the address is defined plus the displacement into the CSECT of the address. Addresses are more like temperatures with a certain type of value (Centigrade vs. Fahrenheit, for example). What this allows ASMA to do is during a later phase of the assembly to assign an address to the CSECT start based upon the region in which it resides and by carrying with the address the control section it eventually allows resolution of addresses between multiple control sections during the assembly. This allows ASMA to essentially perform a linking function between different control sections during assembly without a linkage editor. This is extremely valuable when multiple regions are produced and multiple control sections, each of which has its own explicit starting location in real memory and which needs to interact during execution. The ability to then export regions to an LDID is also useful when creating the load content.

Regions are a concept foreign to legacy assemblers but is very useful for bare-metal programs which need to place pieces of code in different memory locations. This facility does not exist with legacy assemblers at all. CSECT's are placed in memory sequentially with no ability to specify the starting address of the CSECT. The assembler decides the address in the assembly with out the programmer being able to place anything at an explicit location. At least by the assembler.

Just as there is an unnamed control section, ASMA has an unnamed region when one is not explicitly named in the ASMA START operation. I suspect that is why the address is considered ABS, for absolute, but is still an "address".

While the situation that crops up occasionally with address usage may be annoying, it is at its core the foundation for a number of major ASMA capabilities unavailable in legacy assemblers. Yes, I know some of them are available from an external linkage editor which ASMA lacks. It partly lacks an editor because in many cases it does not need one.

I hope for those reading these issues, this is a more complete response and the reader gains an appreciation of why it is not going to change.

Harold Grovesteen

s390guy commented 3 weeks ago

With regard to the messages. I tried very hard to keep the Python details out of sight for the user. I did not really expect a user to "figure" out what is going on internally, so the information attempts to be informative about what the user can change to address the problem. Changing ASMA, "bug" fixing if you will, was not part of the messaging scheme.

In this case, another alternative could be to change the instruction to one that loads an address.

s390guy commented 3 weeks ago

BTW, The MSL.pdf manual on page 11 defines the RI2 field as "an instruction immediate field". Which is correct for the RIA format used by LGHI. (See asma/msl/PoO.txt) Do not be misled by the R and assume it is REL.

Fish-Git commented 3 weeks ago

So, as the error indicates, ASMA, is NOT treating an address as simply a number. Your assumption is not correct. Addresses are not just numbers in ASMA. Working As Designed.

Yes, I get you do not like the design.

Well, it's not so much that I don't like the design (even though it's true, but only just a little bit, not a lot. After all, I fully respect your right to design things which work best for your product), it's just that such a design is so unexpected (foreign) to me that I keep forgetting about such design decisions!  :)

That is to say, such errors keep catching me off guard. When they occur, it's difficult for me to determine (guess) whether they're likely being caused by a design decision or whether they're being caused by a simple bug/oversight. My apologies.

The source of the error is how addresses are handled within ASMA for the purpose of calculations. Addresses are tagged as "addresses" and the attribute remains with the result of calculations that adjusts the address (+ or -). So F0+65536-63 still has the "address" tag.

The instruction formats require, integers. So the LGFI instruction must use an integer not an "address".

Ah. Okay. I guess that makes sense.

The only way to remove the "address" attribute is to subtract from F0 another address to create an integer, or in this case simply use the integer X'800'.

(Doh!) Of course. How silly of me. My brain hasn't been working as well as usual lately. Must be the stress of my still unresolved workload. (I'm making progress, but not quickly enough for my liking, that I probably just panicked. My apologies.)

I am assuming you want to make the code flexible enough to change the position of F0 in the future.

Well, as I said, I didn't write it (Jürgen did), so yes, I can only presume the same thing.

As a solution, I would suggest that you create somewhere in the code a symbol equated to an integer, like this:

FODISP   EQU   X'800'
         ORG   PRNOTEST+FODISP
FO       DS    0X             first operand

And in the LGFI instruction, use F0DISP instead of F0. Continue to use F0 in the rest of the program when an instruction uses an actual address. If you need to change where F0 is actually placed , adjust the F0DISP equate.

Of course! THANK YOU! I feel so stupid. Like I said, I must have panicked.

I did not test this, but I believe it will solve the immediate problem. Feel free to use as many expletives as you like if it makes you feel better when the explain why you are doing this. LOL

(LOL!) Thank you Harold. You're a good friend.  :)

(p.s. Your solution worked just fine of course..)

Fish-Git commented 3 weeks ago

While the situation that crops up occasionally with address usage may be annoying, it is at its core the foundation for a number of major ASMA capabilities unavailable in legacy assemblers. Yes, I know some of them are available from an external linkage editor which ASMA lacks. It partly lacks an editor because in many cases it does not need one.

I hope for those reading these issues, this is a more complete response and the reader gains an appreciation of why it is not going to change.

Harold Grovesteen

Makes absolute perfect sense, Harold. Your design decision is a good one. We users (well, perhaps not all user, but THIS particular user in this particular case!) just sometimes have trouble keeping such things in mind when such situations occur.

So as much as you may wish that we users try to keep such things in mind when such things occur, we would also like to ask that you try to keep in mind that it can be difficult for some of us (me in particular!) to keep such things in mind when we report such things. That is to say, it can be easy for us (me!) to forget about such things and end up mistakenly reporting them as bugs instead.

So please forgive us (me!) when we do. We don't mean to. It just happens. Such perfectly reasonable and necessary design decisions are so atypical from those made for the products we're used to using, that it's easy for us to forget.

As always, I, and I'm sure others, greatly appreciate your continued patience with us/me.  :)

Fish-Git commented 3 weeks ago

BTW, The MSL.pdf manual on page 11 defines the RI2 field as "an instruction immediate field". Which is correct for the RIA[sic] format used by LGHI.   . . .   Do not be misled by the R and assume it is REL.

(I think you meant RIL(a))

Yep. You're right again.

It's just that page 5-8 of the Principles of Operation manual documents the meaning of I2 and RI2 instruction operands differently, thus leading to my understanable confusion. ASMA's usage is correct, just as IBM's is too! Both are correct!

But because they're different from one another (and so easy for me to forget that not everything may be as it seems when it comes to ASMA), it's easy for me to make such understandable mistaken assumptions.

In any case, no big deal. We're cool. I'm all straightened out now. My issue is resolved, so I'm happy.  :)

(and a BIG THANKS for the expedited handling too! You're a pal!)