#define THREE_PASS
#define LISTING
#define RELOCATION
+#define DEBUG 2 /* as long as we are testing ... */
#undef valu_t
#define valu_t long
/*
- * (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 */
/*
- * (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
-/* $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
*/
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",
#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
:
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); }
: 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
| 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;
| 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
}
;
-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;
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
}
;
-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;
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
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;
}
;
oper
: OP0
| OP1_O opnd { $$ = $1; }
- | OP1_A ea { $$ = $1; }
| OP1_B expr { $$ = $1;
opnd[0].exp = $2;
RELOMOVE(opnd[0].relo, relonami);
}
| OP2_O_O opnd ',' opnd
{ $$ = $1; }
- | OP2_A_O ea ',' opnd
- { $$ = $1; }
| OP2_O_B opnd ',' expr
{ $$ = $1;
opnd[op_ind].exp = $4;
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
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
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;
}
;
-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++;
- }
- ;
* 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:
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);
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);
}
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) &&
}
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;
}
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);
) {
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)) {
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));
}
}
RELOMOVE(relonami, p->relo);
newrelo(p->exp.typ, RELO4|RELPC);
#endif
+ /* exp.val - 3: see comment above */
emit4((long) p->exp.val - 3);
}
break;
}
}
+/* 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++;
}
break;
case DISPLL_MODE:
case DISPLL_DEF_MODE:
- case ABS:
- case ABS_DEF:
+ case REL:
+ case REL_DEF:
case IMM:
sz += 5;
break;
return sz;
}
+/* Branch with byte or word offset */
branch(opc, exp)
expr_t 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)) {
}
}
+/* 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;
) {
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);
}
}
-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]);
}
}