simplified a bit, and documented better
authorceriel <none@none>
Wed, 17 Jan 1990 16:05:00 +0000 (16:05 +0000)
committerceriel <none@none>
Wed, 17 Jan 1990 16:05:00 +0000 (16:05 +0000)
mach/vax4/as/mach0.c
mach/vax4/as/mach1.c
mach/vax4/as/mach2.c
mach/vax4/as/mach3.c
mach/vax4/as/mach4.c
mach/vax4/as/mach5.c

index 89545f8..09fd412 100644 (file)
@@ -11,6 +11,7 @@
 #define THREE_PASS
 #define LISTING
 #define RELOCATION
+#define DEBUG 2                        /* as long as we are testing ... */
 
 #undef valu_t
 #define valu_t long
index 2cc7164..a727be2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
  * See the copyright notice in the ACK home directory, in the file "Copyright".
  */
 #define RCSID1 "$Header$"
 #define DISPL          16      /* not an addressing mode; used for branch
                                   displacement addressing
                                */
-#define IMM            17      /* immediate mode (only for internal use) */
-#define ABS            18      /* absolute mode (only for internal use) */
-#define ABS_DEF                19      /* absolute deferred mode (only for internal use) */
+#define ABS            17      /* absolute mode (only for internal use) */
+#define IMM            18      /* immediate mode (only for internal use) */
+#define REL            19      /* relative mode (only for internal use) */
+#define REL_DEF                20      /* relative deferred mode (only for internal
+                                  use)
+                               */
+
+/* Some mnemonics used in mach5.c */
+
+#define PC             15      /* program counter */
+#define BRB            0x11    /* opcode of branch with byte offset */
+#define BRW            0x31    /* opcode of branch with word offset */
+#define JMP            0x17    /* opcode of jmp instruction */
 
-#define PC             15      /* special case */
+/* Test if a constant is suitable for literal mode */
 
-#define fit8(z)                (lowb(z) == (z))
-#define fit16(z)       (loww(z) == (z))
 #define literal(z)     (((z) & ~0x3f) == 0)
 
+/* Declarations for operands */
+
 struct operand {
        expr_t  exp;
        int     mode;           /* addressing mode */
        int     reg;            /* register used in addressing mode */
        int     relo;           /* index in relocation table for exp */
-       int     size;           /* size as imposed by instruction */
+       int     size;           /* size as imposed by instruction
+                                  -1 indicates bit-field (no immediate mode
+                                     allowed)
+                                  -2 indicates address (no register mode
+                                     or immediate mode allowed)
+                               */
        int     index_reg;      /* for indexed mode contains index reg,
                                   -1 if not index mode
                                */
 };
 
-extern struct operand opnd[6];
-extern int op_ind;
+extern struct operand opnd[6]; /* maximum number of operands of a VAX
+                                  instruction is 6
+                               */
+extern int op_ind;             /* index in opng array */
index 58d53e1..09289db 100644 (file)
@@ -1,11 +1,29 @@
 /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
  * See the copyright notice in the ACK home directory, in the file "Copyright".
  */
 #define RCSID2 "$Header$"
 
 /*
-* VAX-11 machine dependent yacc declarations
+ * VAX-11 machine dependent yacc declarations
+ */
+
+/* operands are indicated with a letter combination:
+       b -     general operand of byte size
+       w -     general operand of word size
+       l -     general operand of long size
+       u -     general operand of > long size (immediate mode is not
+               implemented for this size, and neither are immediate
+               floating point encodings
+       A -     an operand of which the address is taken (so, no register
+               or immediate mode)
+       V -     a bit-field operand (no immediate mode)
+       Bb -    byte offset branch
+       Bw -    word offset branch
+       Bl -    long offset branch
+       Bx -    branch, size of offset determined by instruction
+       Be -    extended conditional branch; the instruction may be replaced
+               by a reverse-conditional branch over a branch or jump
 */
 
 %token <y_word> REG
 %token <y_word>        OP5_u_b_u_l_u, OP5_u_w_u_l_u, OP5_w_A_A_w_A, OP5_w_A_b_w_A
 %token <y_word>        OP6_b_w_A_b_w_A, OP6_l_l_l_l_l_l, OP6_w_A_b_A_w_A,
                OP6_w_A_w_A_w_A
-%token <y_word>
+
+/* operand types:
+       O -     the b, w, l, A and V operands (they all fall into the same
+               syntactic category)
+       B -     branch offsets (these do not result in an addressing mode
+               byte)
+*/
 %type <y_word> OP1_O, OP1_B
-%type <y_word> OP2_O_O, OP2_A_O, OP2_O_B, OP2_O_A
-%type <y_word> OP3_O_O_O, OP3_O_O_B, OP3_O_O_A, OP3_O_A_A, OP3_O_A_O
-%type <y_word> OP4_O_O_O_O, OP4_O_O_O_B, OP4_O_A_O_A, OP4_O_A_A_O,
-               OP4_O_A_A_A, OP4_A_O_O_A
-%type <y_word> OP5_O_A_A_O_A, OP5_O_A_O_O_A, OP5_O_O_O_O_O
-%type <y_word> OP6_O_O_O_O_O_O, OP6_O_A_O_A_O_A, OP6_O_O_A_O_O_A
+%type <y_word> OP2_O_O, OP2_O_B
+%type <y_word> OP3_O_O_O, OP3_O_O_B
+%type <y_word> OP4_O_O_O_O, OP4_O_O_O_B
+%type <y_word> OP5_O_O_O_O_O
+%type <y_word> OP6_O_O_O_O_O_O
 %type <y_word> CASE_O_O_O
-
 %type <y_word> oper
index a5942f7..7edc1fe 100644 (file)
@@ -1,8 +1,9 @@
-/* $Header$ */
 /*
  * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
  * See the copyright notice in the ACK home directory, in the file "Copyright".
  */
+#define RCSID3 "$Header$"
+
 /*
  * VAX-11 keywords
  */
@@ -33,6 +34,8 @@
    size.
    For now, immediate floating point and immediate values of size > 4 are not
    implemented. _u is used for this.
+   The valu_t field is used for the opcode. Most opcodes take one byte.
+   The ones that don't take two bytes.
 */
 
 /* integer arithmetic and logical instructions */
 
 /* Other VAX-11 instructions */
 
-0,             OP1_Bw,         0xfeff,         "bugw", /* ??? */
-0,             OP1_Bl,         0xfdff,         "bugl", /* ??? */
+/* BSD 4.3 adb has a different opinion of the bugw and bugl instructions:
+   it thinks that an addressing mode byte is required. However, according
+   to the VAX-11 Architecture Reference Manual, Revision 6.1, 1982, the
+   access type is b, which means that the operand is a branch displacement.
+*/
+0,             OP1_Bw,         0xfeff,         "bugw",
+0,             OP1_Bl,         0xfdff,         "bugl",
 
 0,             OP3_b_w_A,      0x0c,           "prober",
 0,             OP3_b_w_A,      0x0d,           "probew",
index c81fb47..537b42f 100644 (file)
@@ -5,16 +5,10 @@
 #define RCSID4 "$Header$"
 
 /*
-* VAX-11 machine dependent yacc syntax rules
-*/
+ * VAX-11 machine dependent yacc syntax rules
+ */
 
-/* _b, _w, and _l are ordinary READ/MODIFY/WRITE operands, the letter indicates
-       the size,
-   A means effective ADDRESS (must be memory),
-   B means branch displacement,
-   V means effective address or register;
-   Here, no difference is made between Modify and Write.
-*/
+/* Branch instructions with as yet unknown size get special treatment */
 
 operation
        :
@@ -27,7 +21,7 @@ operation
                                        emit1((int)$2&0xff);
                                        emit1((int)$2>>8);
                                  }
-                                 operands(op_ind);
+                                 operands();
                                }
        |       OP1_Bx expr     { branch($1, $2); }
        |       OP1_Be expr     { op_ind = 0; ext_branch($1, $2); }
@@ -45,7 +39,8 @@ OP1_O
        :       OP1_b           { opnd[0].size = 1; $$ = $1; }
        |       OP1_w           { opnd[0].size = 2; $$ = $1; }
        |       OP1_l           { opnd[0].size = 4; $$ = $1; }
-       |       OP1_u
+       |       OP1_A           { opnd[0].size = -2; $$ = $1; }
+       |       OP1_u           { opnd[0].size = 0; $$ = $1; }
        ;
 
 OP1_B
@@ -71,20 +66,15 @@ OP2_O_O
        |       OP2_w_l         { opnd[0].size = 2; opnd[1].size = 4; $$ = $1; }
        |       OP2_w_u         { opnd[0].size = 2; opnd[1].size = 0; $$ = $1; }
        |       OP2_w_w         { opnd[0].size = 2; opnd[1].size = 2; $$ = $1; }
-       ;
-
-OP2_A_O
-       :       OP2_A_l         { opnd[1].size = 4; $$ = $1; }
+       |       OP2_A_l         { opnd[0].size = -2;opnd[1].size = 4; $$ = $1; }
+       |       OP2_l_A         { opnd[0].size = 4; opnd[1].size = -2;$$ = $1; }
+       |       OP2_A_A         { opnd[0].size = -2;opnd[1].size = -2;$$ = $1; }
        ;
 
 OP2_O_B
        :       OP2_l_Bb        { opnd[0].size = 4; opnd[1].size = 1; $$ = $1; }
        ;
 
-OP2_O_A
-       :       OP2_l_A         { opnd[0].size = 4; $$ = $1; }
-       ;
-
 OP3_O_O_O
        :       OP3_b_b_b       { opnd[0].size = 1; opnd[1].size = 1;
                                  opnd[2].size = 1; $$ = $1;
@@ -104,6 +94,21 @@ OP3_O_O_O
        |       OP3_w_w_w       { opnd[0].size = 2; opnd[1].size = 2;
                                  opnd[2].size = 2; $$ = $1;
                                }
+       |       OP3_b_w_A       { opnd[0].size = 1; opnd[1].size = 2;
+                                 opnd[2].size = -2; $$ = $1;
+                               }
+       |       OP3_l_w_A       { opnd[0].size = 4; opnd[1].size = 2;
+                                 opnd[2].size = -2; $$ = $1;
+                               }
+       |       OP3_u_w_A       { opnd[0].size = 0; opnd[1].size = 2;
+                                 opnd[2].size = -2; $$ = $1;
+                               }
+       |       OP3_w_A_A       { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = -2; $$ = $1;
+                               }
+       |       OP3_w_A_l       { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = 4; $$ = $1;
+                               }
        ;
 
 OP3_O_O_B
@@ -115,20 +120,6 @@ OP3_O_O_B
                                }
        ;
 
-OP3_O_O_A
-       :       OP3_b_w_A       { opnd[0].size = 1; opnd[1].size = 2; $$ = $1; }
-       |       OP3_l_w_A       { opnd[0].size = 4; opnd[1].size = 2; $$ = $1; }
-       |       OP3_u_w_A       { opnd[0].size = 0; opnd[1].size = 2; $$ = $1; }
-       ;
-
-OP3_O_A_A
-       :       OP3_w_A_A       { opnd[0].size = 2; $$ = $1; }
-       ;
-
-OP3_O_A_O
-       :       OP3_w_A_l       { opnd[0].size = 2; opnd[2].size = 4; $$ = $1; }
-       ;
-
 OP4_O_O_O_O
        :       OP4_l_b_V_l     { opnd[0].size = 4; opnd[1].size = 1;
                                  opnd[2].size = -1; opnd[3].size = 4;
@@ -146,6 +137,22 @@ OP4_O_O_O_O
                                  opnd[2].size = 4; opnd[3].size = 4;
                                  $$ = $1;
                                }
+       |       OP4_w_A_w_A     { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = 2; opnd[3].size = -2;
+                                 $$ = $1;
+                               }
+       |       OP4_w_A_A_A     { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = -2; opnd[3].size = -2;
+                                 $$ = $1;
+                               }
+       |       OP4_A_l_w_A     { opnd[0].size = -2; opnd[1].size = 4;
+                                 opnd[2].size = 2; opnd[3].size = -2;
+                                 $$ = $1;
+                               }
+       |       OP4_w_A_A_b     { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = -2; opnd[3].size = 1;
+                                 $$ = $1;
+                               }
        ;       
 
 OP4_O_O_O_B
@@ -167,32 +174,6 @@ OP4_O_O_O_B
                                }
        ;
 
-OP4_O_A_O_A
-       :       OP4_w_A_w_A     { opnd[0].size = 2; opnd[2].size = 2; $$ = $1; }
-       ;
-
-OP4_O_A_A_O
-       :       OP4_w_A_A_b     { opnd[0].size = 2; opnd[3].size = 1; $$ = $1; }
-       ;
-
-OP4_O_A_A_A
-       :       OP4_w_A_A_A     { opnd[0].size = 2; $$ = $1; }
-       ;
-
-OP4_A_O_O_A
-       :       OP4_A_l_w_A     { opnd[1].size = 4; opnd[2].size = 2; $$ = $1; }
-       ;
-
-OP5_O_A_A_O_A
-       :       OP5_w_A_A_w_A   { opnd[0].size = 2; opnd[3].size = 2; $$ = $1; }
-       ;
-
-OP5_O_A_O_O_A
-       :       OP5_w_A_b_w_A   { opnd[0].size = 2; opnd[3].size = 2;
-                                 opnd[2].size = 1; $$ = $1;
-                               }
-       ;
-
 OP5_O_O_O_O_O
        :       OP5_u_b_u_l_u   { opnd[0].size = 0; opnd[1].size = 1;
                                  opnd[2].size = 0; opnd[3].size = 4;
@@ -202,6 +183,14 @@ OP5_O_O_O_O_O
                                  opnd[2].size = 0; opnd[3].size = 4;
                                  opnd[4].size = 0; $$ = $1;
                                }
+       |       OP5_w_A_A_w_A   { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = -2; opnd[3].size = 2;
+                                 opnd[4].size = -2; $$ = $1;
+                               }
+       |       OP5_w_A_b_w_A   { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = 1; opnd[3].size = 2;
+                                 opnd[4].size = -2; $$ = $1;
+                               }
        ;
 
 OP6_O_O_O_O_O_O
@@ -210,20 +199,19 @@ OP6_O_O_O_O_O_O
                                  opnd[4].size = 4; opnd[5].size = 4;
                                  $$ = $1;
                                }
-       ;
-
-OP6_O_A_O_A_O_A
-       :       OP6_w_A_b_A_w_A { opnd[0].size = 2; opnd[2].size = 1;
-                                 opnd[4].size = 2; $$ = $1;
+       |       OP6_w_A_b_A_w_A { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = 1; opnd[3].size = -2;
+                                 opnd[4].size = 2; opnd[5].size = -2;
+                                 $$ = $1;
                                }
-       |       OP6_w_A_w_A_w_A { opnd[0].size = 2; opnd[2].size = 2;
-                                 opnd[4].size = 2; $$ = $1;
+       |       OP6_w_A_w_A_w_A { opnd[0].size = 2; opnd[1].size = -2;
+                                 opnd[2].size = 2; opnd[3].size = -2;
+                                 opnd[4].size = 2; opnd[5].size = -2;
+                                 $$ = $1;
                                }
-       ;
-
-OP6_O_O_A_O_O_A
-       :       OP6_b_w_A_b_w_A { opnd[0].size = 1; opnd[1].size = 2;
-                                 opnd[3].size = 1; opnd[4].size = 2;
+       |       OP6_b_w_A_b_w_A { opnd[0].size = 1; opnd[1].size = 2;
+                                 opnd[2].size = -2; opnd[3].size = 1;
+                                 opnd[4].size = 2; opnd[5].size = -2;
                                  $$ = $1;
                                }
        ;
@@ -243,7 +231,6 @@ CASE_O_O_O
 oper
        :       OP0
        |       OP1_O opnd      { $$ = $1; }
-       |       OP1_A ea        { $$ = $1; }
        |       OP1_B expr      { $$ = $1;
                                  opnd[0].exp = $2;
                                  RELOMOVE(opnd[0].relo, relonami);
@@ -252,8 +239,6 @@ oper
                                }
        |       OP2_O_O opnd ',' opnd   
                                { $$ = $1; }
-       |       OP2_A_O ea ',' opnd
-                               { $$ = $1; }
        |       OP2_O_B opnd ',' expr
                                { $$ = $1;
                                  opnd[op_ind].exp = $4;
@@ -261,10 +246,6 @@ oper
                                  opnd[op_ind].mode = DISPL;
                                  op_ind++;
                                }
-       |       OP2_A_A ea ',' ea
-                               { $$ = $1; }
-       |       OP2_O_A opnd ',' ea
-                               { $$ = $1; }
        |       OP3_O_O_O opnd ',' opnd ',' opnd
                                { $$ = $1; }
        |       OP3_O_O_B opnd ',' opnd ',' expr
@@ -274,12 +255,6 @@ oper
                                  opnd[op_ind].mode = DISPL;
                                  op_ind++;
                                }
-       |       OP3_O_O_A opnd ',' opnd ',' ea
-                               { $$ = $1; }
-       |       OP3_O_A_A opnd ',' ea ',' ea
-                               { $$ = $1; }
-       |       OP3_O_A_O opnd ',' ea ',' opnd
-                               { $$ = $1; }
        |       OP4_O_O_O_O opnd ',' opnd ',' opnd ',' opnd
                                { $$ = $1; }
        |       OP4_O_O_O_B opnd ',' opnd ',' opnd ',' expr
@@ -289,58 +264,44 @@ oper
                                  opnd[op_ind].mode = DISPL;
                                  op_ind++;
                                }
-       |       OP4_O_A_O_A opnd ',' ea ',' opnd ',' ea
-                               { $$ = $1; }
-       |       OP4_O_A_A_O opnd ',' ea ',' ea ',' opnd
-                               { $$ = $1; }
-       |       OP4_A_O_O_A ea ',' opnd ',' opnd ',' ea
-                               { $$ = $1; }
-       |       OP4_O_A_A_A opnd ',' ea ',' ea ',' ea
-                               { $$ = $1; }
-       |       OP5_O_A_A_O_A opnd ',' ea ',' ea ',' opnd ',' ea
-                               { $$ = $1; }
-       |       OP5_O_A_O_O_A opnd ',' ea ',' opnd ',' opnd ',' ea
-                               { $$ = $1; }
        |       OP5_O_O_O_O_O opnd ',' opnd ',' opnd ',' opnd ',' opnd
                                { $$ = $1; }
        |       OP6_O_O_O_O_O_O opnd ',' opnd ',' opnd ',' opnd ',' opnd ',' opnd
                                { $$ = $1; }
-       |       OP6_O_A_O_A_O_A opnd ',' ea ',' opnd ',' ea ',' opnd ',' ea
-                               { $$ = $1; }
-       |       OP6_O_O_A_O_O_A opnd ',' opnd ',' ea ',' opnd ',' opnd ',' ea
-                               { $$ = $1; }
        |       CASE_O_O_O opnd ',' opnd ',' opnd
                                { $$ = $1; }
        ;
 
 opnd
-       :       ea
-       |       immediate
-       |       REG             { opnd[op_ind].mode = REG_MODE;
+       :       REG             { opnd[op_ind].mode = REG_MODE;
                                  opnd[op_ind].reg = $1;
                                  opnd[op_ind].index_reg = -1;
                                  op_ind++;
                                }
-       ;
-
-ea
-       :       eax             { opnd[op_ind].index_reg = -1;
+       |       eax             { opnd[op_ind].index_reg = -1;
                                  op_ind++;
                                }
        |       eax '[' REG ']' { opnd[op_ind].index_reg = $3;
                                  op_ind++;
                                }
-       |       immediate '[' REG ']'
-                               { opnd[op_ind-1].index_reg = $3;
-                               }
        ;
 eax
-       :       expr            { opnd[op_ind].exp = $1;
-                                 opnd[op_ind].mode = ABS;
+       :       '$' expr        { opnd[op_ind].mode = IMM;
+                                 opnd[op_ind].exp = $2;
+                                 opnd[op_ind].index_reg = -1;
                                  RELOMOVE(opnd[op_ind].relo, relonami);
                                }
        |       '*' expr        { opnd[op_ind].exp = $2;
-                                 opnd[op_ind].mode = ABS_DEF;
+                                 opnd[op_ind].mode = REL_DEF;
+                                 RELOMOVE(opnd[op_ind].relo, relonami);
+                               }
+       |       expr            { opnd[op_ind].exp = $1;
+                                 opnd[op_ind].mode = REL;
+                                 RELOMOVE(opnd[op_ind].relo, relonami);
+                               }
+       |       '*' '$' expr    { opnd[op_ind].mode = ABS;
+                                 opnd[op_ind].exp = $3;
+                                 opnd[op_ind].index_reg = -1;
                                  RELOMOVE(opnd[op_ind].relo, relonami);
                                }
        |       '(' REG ')'     { opnd[op_ind].mode = REGDEF_MODE;
@@ -370,11 +331,3 @@ eax
                                }
        ;
 
-immediate
-       :       '$' expr        { opnd[op_ind].mode = IMM;
-                                 opnd[op_ind].exp = $2;
-                                 opnd[op_ind].index_reg = -1;
-                                 RELOMOVE(opnd[op_ind].relo, relonami);
-                                 op_ind++;
-                               }
-       ;
index 42e3f4b..bdedca4 100644 (file)
@@ -8,21 +8,26 @@
  * VAX-11 Machine dependent C declarations
  */
 
+/* Opcode of branch on reversed condition. */
+#define rev_cond_branch(opc)   ((opc) ^ 1)
+
+/* Process one operand. */
 static
 oprnd(p)
        register struct operand *p;
 {
-       /*      Process one operand */
-
        int     sm;
 
        if (p->index_reg >= 0 && p->mode != DISPL) {
-               /* indexed mode; emit */
+               /* Indexed mode; emit */
                emit1((INDEX_MODE << 4) | p->index_reg);
        }
 
        switch(p->mode) {
        case REG_MODE:
+               if (p->size == -2 && p->index_reg < 0) {
+                       serror("register mode not allowed here");
+               }
                emit1((REG_MODE << 4) | p->reg);
                break;
        case REGDEF_MODE:
@@ -39,7 +44,12 @@ oprnd(p)
                break;
        case DISPLL_MODE:
        case DISPLL_DEF_MODE:
+               /* Three possible sizes: 1, 2, and 4 (and 0, but this is
+                  not implemented). Therefore, we need two bits in the
+                  optimize table.
+               */
                if (small(p->exp.typ == S_ABS && fitw(p->exp.val), 2)) {
+                       /* We gained two bytes; see if we can gain another. */
                        if (small(fitb(p->exp.val), 1)) {
                                /* DISPLB_MODE or DISPLB_DEF_MODE */
                                emit1(((p->mode-4)<<4) | p->reg);
@@ -51,8 +61,8 @@ oprnd(p)
                                emit2((int)(p->exp.val));
                        }
                }
-               else {
-                       small(0, 1);    /* dummy call */
+               else {  /* We need 4 bytes here. */
+                       small(0, 1);    /* dummy call too keep bits in sync */
                        emit1((p->mode<<4) | p->reg);
 #ifdef RELOCATION
                        RELOMOVE(relonami, p->relo);
@@ -62,7 +72,7 @@ oprnd(p)
                }
                break;
        case DISPL:
-               /* a displacement */
+               /* A displacement. The p->size field contains the size. */
                p->exp.val -= (DOTVAL + p->size);
                if ((pass == PASS_2) &&
                    (p->exp.val > 0) &&
@@ -79,9 +89,18 @@ oprnd(p)
                }
                if (p->size == 1) emit1((int)(p->exp.val));
                else if (p->size == 2) emit2((int)(p->exp.val));
-               else emit4(p->exp.val);
+               else {
+#ifdef RELOCATION
+                       RELOMOVE(relonami, p->relo);
+                       newrelo(p->exp.typ, RELO4|RELPC);
+#endif
+                       emit4(p->exp.val);
+               }
                break;
        case IMM:
+               /* Immediate mode; either literal mode or auto-increment
+                  of program counter.
+               */
                if (p->size < 0) {
                        serror("immediate mode not allowed here");
                        p->size = 4;
@@ -121,8 +140,22 @@ oprnd(p)
                }
                break;
        case ABS:
-       case ABS_DEF:
-               if (p->mode == ABS) p->mode = DISPLL_MODE;
+               /* Absolute mode (is auto-increment deferred with respect
+                  to the program counter).
+               */
+               emit1((AI_DEF_MODE << 4) | PC);
+#ifdef RELOCATION
+               RELOMOVE(relonami, p->relo);
+               newrelo(p->exp.typ, RELO4);
+#endif
+               emit4(p->exp.val);
+               break;
+       case REL:
+       case REL_DEF:
+               /* Relative or relative deferred is actually displacement
+                  or displacement deferred, but relative to program counter.
+               */
+               if (p->mode == REL) p->mode = DISPLL_MODE;
                else p->mode = DISPLL_DEF_MODE;
                p->reg = PC;
                p->exp.val -= (DOTVAL + 2);
@@ -134,6 +167,10 @@ oprnd(p)
                   ) {
                        p->exp.val -= DOTGAIN;
                }
+               /* Why test for exp.val - 1? Well, if we need a word for
+                  the offset, we actually generate one byte more, and this
+                  is reflected in the value of the program counter.
+               */
                sm = fitw(p->exp.val - 1);
                if ((p->exp.typ & ~S_DOT) != DOTTYP) sm = 0;
                if (small(sm, 2)) {
@@ -145,6 +182,7 @@ oprnd(p)
                        else {
                                /* DISPLW_MODE or DISPLW_DEF_MODE */
                                emit1(((p->mode-2)<<4) | p->reg);
+                               /* exp.val - 1: see comment above */
                                emit2((int)(p->exp.val - 1));
                        }
                }
@@ -155,6 +193,7 @@ oprnd(p)
                        RELOMOVE(relonami, p->relo);
                        newrelo(p->exp.typ, RELO4|RELPC);
 #endif
+                       /* exp.val - 3: see comment above */
                        emit4((long) p->exp.val - 3);
                }
                break;
@@ -163,16 +202,15 @@ oprnd(p)
        }
 }
 
+/* Give an upper bound on the size of the operands */
 static int
 size_ops()
 {
-       /*      Give an upper bound on the size of the operands
-       */
        register struct operand *p = &opnd[0];
        register int i;
        register int sz = 0;
 
-       for (i = 0; i < op_ind; i++) {
+       for (i = op_ind; i > 0; i--) {
                if (p->index_reg >= 0 && p->mode != DISPL) {
                        sz++;
                }
@@ -186,8 +224,8 @@ size_ops()
                        break;
                case DISPLL_MODE:
                case DISPLL_DEF_MODE:
-               case ABS:
-               case ABS_DEF:
+               case REL:
+               case REL_DEF:
                case IMM:
                        sz += 5;
                        break;
@@ -202,6 +240,7 @@ size_ops()
        return sz;
 }
 
+/* Branch with byte or word offset  */
 branch(opc, exp)
        expr_t exp;
 {
@@ -212,8 +251,11 @@ branch(opc, exp)
           ) {
                exp.val -= DOTGAIN;
        }
+       /* For the reason of exp.val-1, see the comment at the generation
+          of the RELative addressing mode.
+       */
        if (pass >= PASS_2 &&
-           ((exp.typ & ~S_DOT) != DOTTYP || ! fitw(exp.val-1))) {
+           ((exp.typ & ~S_DOT) != DOTTYP || ! fitw(exp.val - 1))) {
                serror("label too far");
        }
        if (small(fitb(exp.val) && ((exp.typ & ~S_DOT) == DOTTYP), 1)) {
@@ -226,11 +268,15 @@ branch(opc, exp)
        }
 }
 
+/* Extended conditional branch instructions: if offset is too far,
+   they are replaced by a reversed conditional branch over a word-branch or
+   jump.
+*/
 ext_branch(opc, exp)
        expr_t exp;
 {
        int sm;
-       int gain = opc == 0x11 ? 1 : 3;
+       int gain = opc == BRB ? 1 : 3;
        valu_t  val, d2 = DOTVAL + 2;
 
        exp.val -= d2;
@@ -240,34 +286,51 @@ ext_branch(opc, exp)
           ) {
                exp.val -= DOTGAIN;
        }
+       /* We have not generated the operands yet and cannot do so
+          because we don't know the opcode yet and have to generate that
+          first. Therefore, we make a conservative guess of the size
+          of the operands in case the branch is backwards. If it is
+          forwards, the (sizes of the) operands do not matter.
+       */
        if (exp.val < 0) val = exp.val - size_ops();
        else val = exp.val;
        sm = fitw(val);
        if ((exp.typ & ~S_DOT) != DOTTYP) sm = 0;
+       /* We gain three bytes if the offset fits in a word; for a
+          jump we also need an addressing mode byte.
+       */
        if (small(sm, 3)) {
+               /* Here we can gain 3 bytes if the extended branch is
+                  conditional and the offset fits in a byte. Otherwise,
+                  if the offset fits in a byte we gain 1 byte.
+               */
                if (small(fitb(val), gain)) {
                        emit1(opc);
-                       operands(op_ind);
+                       operands();
+                       /* Adjust exp.val for operand sizes. Keep into account
+                          that we already generated the opcode(!). This
+                          accounts for the "+ 1" instead of "+ 2".
+                       */
                        emit1((int) (exp.val - (DOTVAL + 1 - d2)));
                }
                else {
-                       if (opc != 0x11) {
-                               emit1(opc^1);
-                               operands(op_ind);
+                       if (opc != BRB) {
+                               emit1(rev_cond_branch(opc));
+                               operands();
                                emit1(3);
                        }
-                       emit1(0x31);
+                       emit1(BRW);
                        emit2((int) (exp.val - (DOTVAL + 2 - d2)));
                }
        }
        else {
-               small(0, gain); /* dummy call */
-               if (opc != 0x11) {
-                       emit1(opc ^ 1);
-                       operands(op_ind);
+               small(0, gain); /* dummy call to keep bittab in sync */
+               if (opc != BRB) {
+                       emit1(rev_cond_branch(opc));
+                       operands();
                        emit1(6);
                }
-               emit1(0x17);    /* jmp */
+               emit1(JMP);
                emit1((DISPLL_MODE << 4) | PC);
 #ifdef RELOCATION
                newrelo(exp.typ, RELO4|RELPC);
@@ -276,11 +339,12 @@ ext_branch(opc, exp)
        }
 }
 
-operands(cnt)
+/* Generate code for the operands */
+operands()
 {
        register int i;
 
-       for (i = 0; i < cnt; i++) {
+       for (i = 0; i < op_ind; i++) {
                oprnd(&opnd[i]);
        }
 }