From: ceriel Date: Wed, 17 Jan 1990 16:05:00 +0000 (+0000) Subject: simplified a bit, and documented better X-Git-Tag: release-5-5~1934 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=7913b6800a713fb31c14eb49ce50551f920230df;p=ack.git simplified a bit, and documented better --- diff --git a/mach/vax4/as/mach0.c b/mach/vax4/as/mach0.c index 89545f8b3..09fd4123c 100644 --- a/mach/vax4/as/mach0.c +++ b/mach/vax4/as/mach0.c @@ -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 diff --git a/mach/vax4/as/mach1.c b/mach/vax4/as/mach1.c index 2cc716425..a727be20c 100644 --- a/mach/vax4/as/mach1.c +++ b/mach/vax4/as/mach1.c @@ -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$" @@ -26,26 +26,43 @@ #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 */ diff --git a/mach/vax4/as/mach2.c b/mach/vax4/as/mach2.c index 58d53e103..09289db32 100644 --- a/mach/vax4/as/mach2.c +++ b/mach/vax4/as/mach2.c @@ -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 REG @@ -25,14 +43,18 @@ %token 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 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 + +/* 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 OP1_O, OP1_B -%type OP2_O_O, OP2_A_O, OP2_O_B, OP2_O_A -%type OP3_O_O_O, OP3_O_O_B, OP3_O_O_A, OP3_O_A_A, OP3_O_A_O -%type 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 OP5_O_A_A_O_A, OP5_O_A_O_O_A, OP5_O_O_O_O_O -%type OP6_O_O_O_O_O_O, OP6_O_A_O_A_O_A, OP6_O_O_A_O_O_A +%type OP2_O_O, OP2_O_B +%type OP3_O_O_O, OP3_O_O_B +%type OP4_O_O_O_O, OP4_O_O_O_B +%type OP5_O_O_O_O_O +%type OP6_O_O_O_O_O_O %type CASE_O_O_O - %type oper diff --git a/mach/vax4/as/mach3.c b/mach/vax4/as/mach3.c index a5942f7c0..7edc1febf 100644 --- a/mach/vax4/as/mach3.c +++ b/mach/vax4/as/mach3.c @@ -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 */ @@ -409,8 +412,13 @@ /* 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", diff --git a/mach/vax4/as/mach4.c b/mach/vax4/as/mach4.c index c81fb47c5..537b42fe1 100644 --- a/mach/vax4/as/mach4.c +++ b/mach/vax4/as/mach4.c @@ -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++; - } - ; diff --git a/mach/vax4/as/mach5.c b/mach/vax4/as/mach5.c index 42e3f4b3e..bdedca401 100644 --- a/mach/vax4/as/mach5.c +++ b/mach/vax4/as/mach5.c @@ -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]); } }