Introduction
.PP
A \fBcode expander\fR (\fBce\fR for short) is a part of the
-Amsterdam Compiler Kit (\fBACK\fR) and provides the user with
+Amsterdam Compiler Kit
+.[
+toolkit
+.]
+(\fBACK\fR) and provides the user with
high-speed generation of medium-quality code. Although conceptually
equivalent to the more usual \fBcode generator\fR, it differs in some
aspects.
is first fed to the preprocessor. The output of the preprocessor goes
into the appropriate front end, which produces EM
.[
-Tanenbaum toolkit
+block
.]
(a
machine independent low level intermediate code). The generated EM code is fed
.PP
As already indicated, the compound table does not exist either. Instead, each
assembly instruction in the as_table is converted to a routine generating C
-code
.[
Kernighan
.]
+code
to generate C code to call the \fBback\fR-primitives. The EM_table is
converted into a program that for each EM instruction generates a routine,
using the routines generated from the as_table. Execution of the latter program
object code (see section 5), not all the above mentioned constants
and functions have to
be defined. In this
-case, the constants ``BYTES_REVERSED'' and ``WORDS_REVERSED'' are not used.
+case, the constants ``BYTES_REVERSED'' and ``WORDS_\%REVERSED'' are not used.
.NH 1
Description of the as_table
.PP
mov_instr( AX_oper, src);
/* set flag */
@assign( push_waiting, TRUE).
-
+\fR
+.DE
+.DS
+\f5
POP dst ==> @if ( push_waiting)
/* ``mov_instr'' is asg-generated */
mov_instr( dst, AX_oper);
center tab(#);
l c l.
reference#::=#``%'' conversion
-##``('' operand-name ``\(->'' field-name ``)''
+##``('' operand-name ``\->'' field-name ``)''
conversion#::=# printformat
#|#``$''
#|#``dist''
.PP
The following example shows the representative and essential parts of the
8086 ``as.h'' and ``as.c'' files.
-.DS L
.nr PS 10
.nr VS 12
+.LP
+.DS L
\f5
/* Constants and type definitions in as.h */
extern struct t_operand saved_op, *AX_oper;
\fR
+.DE
.nr PS 12
.nr VS 14
-.DE
-.DS L
+.LP
.nr PS 10
.nr VS 12
+.DS L
\f5
/* Some functions in as.c. */
#define RIGHT ')'
#define DOLLAR '$'
-
-process_label( l)
-char *l;
-{
-}
-
-
-process_mnemonic( m)
-char *m;
-{
-}
-
-
process_operand( str, op)
char *str;
struct t_operand *op;
* Note the $-operators
*/
{
- if ( REG( op))
- R233( 0x3, reg, op->reg);
- else if ( ADDR( op)) {
- R233( 0x0, reg, 0x6);
- @reloc2( %$(op->lab), %$(op->off), ABSOLUTE);
- }
- else if ( strcmp( op->expr, "0") == 0)
- switch( op->reg) {
- case SI : R233( 0x0, reg, 0x4);
- break;
+ if ( REG( op))
+ R233( 0x3, reg, op->reg);
+ else if ( ADDR( op)) {
+ R233( 0x0, reg, 0x6);
+ @reloc2( %$(op->lab), %$(op->off), ABSOLUTE);
+ }
+ else if ( strcmp( op->expr, "0") == 0)
+ switch( op->reg) {
+ case SI : R233( 0x0, reg, 0x4);
+ break;
- case DI : R233( 0x0, reg, 0x5);
- break;
+ case DI : R233( 0x0, reg, 0x5);
+ break;
- case BP : R233( 0x1, reg, 0x6); /* exception! */
- @text1( 0);
- break;
+ case BP : R233( 0x1, reg, 0x6); /* exception! */
+ @text1( 0);
+ break;
- case BX : R233( 0x0, reg, 0x7);
- break;
+ case BX : R233( 0x0, reg, 0x7);
+ break;
- default : fprint( STDERR, "Wrong index register %d\n",
- op->reg);
- }
- else {
- @if ( fit_byte( %$(op->expr)))
- switch( op->reg) {
- case SI : R233( 0x1, reg, 0x4);
- break;
-
- case DI : R233( 0x1, reg, 0x5);
- break;
-
- case BP : R233( 0x1, reg, 0x6);
- break;
-
- case BX : R233( 0x1, reg, 0x7);
- break;
-
- default : fprint( STDERR, "Wrong index register %d\n",
- op->reg);
- }
- @text1( %$(op->expr));
- @else
- switch( op->reg) {
- case SI : R233( 0x2, reg, 0x4);
- break;
-
- case DI : R233( 0x2, reg, 0x5);
- break;
-
- case BP : R233( 0x2, reg, 0x6);
- break;
-
- case BX : R233( 0x2, reg, 0x7);
- break;
-
- default : fprint( STDERR, "Wrong index register %d\n",
- op->reg);
- }
- @text2( %$(op->expr));
- @fi
- }
+ default : fprint( STDERR, "Wrong index register %d\en",
+ op->reg);
+ }
+ else {
+ @if ( fit_byte( %$(op->expr)))
+ switch( op->reg) {
+ case SI : R233( 0x1, reg, 0x4);
+ break;
+
+ case DI : R233( 0x1, reg, 0x5);
+ break;
+
+ case BP : R233( 0x1, reg, 0x6);
+ break;
+
+ case BX : R233( 0x1, reg, 0x7);
+ break;
+
+ default : fprint( STDERR, "Wrong index register %d\en",
+ op->reg);
+ }
+ @text1( %$(op->expr));
+ @else
+ switch( op->reg) {
+ case SI : R233( 0x2, reg, 0x4);
+ break;
+
+ case DI : R233( 0x2, reg, 0x5);
+ break;
+
+ case BP : R233( 0x2, reg, 0x6);
+ break;
+
+ case BX : R233( 0x2, reg, 0x7);
+ break;
+
+ default : fprint( STDERR, "Wrong index register %d\en",
+ op->reg);
+ }
+ @text2( %$(op->expr));
+ @fi
+ }
}
\fR
+.DE
.nr PS 12
.nr VS 14
-.DE
.NH 2
Generating assembly code
.PP
change the EM_table and type
.IP
.br
-\f5update\fR \fBC_instr\fR
+\f5
+update\fR \fBC_instr
+\fR
.br
.LP
where \fBC_instr\fR stands for the name of the erroneous EM-instruction.
Write the ``as_table'', ``as.h'', and ``as.c'' files.
.IP \0\03:
type
-.br
+.sp
\f5 install_ceg -obj \fR
-.br
+.sp
The option \f5-obj\fR means that ``back.a'' will contain a library
for generating
ACK.OUT(5ACK) object files, see appendix B.
Then there are two ways to proceed:
.IP \0\01:
recompile the whole EM_table,
-.br
-\f5
-update ALL
-\fR
+.sp
+\f5 update ALL \fR
+.sp
.IP \0\02:
recompile just the few EM-instructions that contained the error,
-\f5
-.br
-update \fBC_instr\fR
-.br
+.sp
+\f5 update \fBC_instr\fR
+.sp
where \fBC_instr\fR is an erroneous EM-instruction.
This has to be done for every EM-instruction that contained the erroneous
assembly instruction.