* Copyright (c) 1982 Regents of the University of California
static char sccsid
[] = "@(#)ascode.c 4.11 %G%";
reg
struct instab
*ip
; /* the instruction */
reg
struct arg
*ap_walk
; /* actual param walk */
reg
int ap_type
; /* actual param type */
reg
int ap_type_mask
; /* masked actual param */
if (!(ITABCHECK(opcode
)))
panic("Botched reference into itab");
yyerror("Too few arguments");
if (nact
> ip
->i_nargs
) {
yyerror("Too many arguments");
* Check argument compatability with instruction template
for (ap_walk
= ap
, i
= 1; i
<= nact
; ap_walk
++, i
++){
ap_type
= ap_walk
->a_atype
;
ap_type_mask
= ap_type
& AMASK
;
* The switch value is >> by TYPLG so that the switch
* code is dense, not implemented as a sequence
* of branches but implemented as a casel.
* In addition, cases ACCI and ACCR are added to force
* switch on the type of fp
switch( ((fetcharg(ip
, i
-1)) & ACCESSMASK
) >> TYPLG
){
if ( !((ap_type_mask
== AEXP
) || (ap_type_mask
== AIMM
)) ){
yyerror("arg %d, branch displacement must be an expression",i
);
case AREG
: yyerror("arg %d, addressing a register",i
);
case AIMM
: if ( !(ap_type
& ASTAR
) ){
yyerror("arg %d, addressing an immediate operand",i
);
case AIMM
: if (!(ap_type
&ASTAR
)) {
yyerror("arg %d, modifying a constant",i
);
} /* end of the switch on fp_type */
if (ap_walk
->a_areg2
==0xF) {
yyerror("arg %d, PC used as index",i
);
case AREG
: yyerror("arg %d, indexing the register file",i
);
case AIMM
: yyerror("arg %d, indexing a constant",i
);
case AINCR
: if (ap_walk
->a_areg1
==ap_walk
->a_areg2
) {
yyerror("arg %d, indexing with modified register",i
);
} /* end of switch on ap_type_mask */
ijxout(opcode
, ap
, nact
);
putins(opcode
, ap
, nact
);
int n
; /* Must be positive */
dotp
->e_xvalue
+= n
; /* at least one byte per arg */
switch(opcode
.Op_eopcode
){
dotp
->e_xvalue
+= 1; /* 1 byte opcode */
dotp
->e_xvalue
+= 2; /* 2 byte opcode */
panic("Bad escape opcode");
for (i
=0; i
<n
; i
++,ap
++) { /* some args take more than 1 byte */
* This switch has been fixed by enumerating the no action
* alternatives (those that have 1 one byte of code)
* so that a casel instruction is emitted.
switch (argtype
&~(AINDX
|ASTAR
)) {
argtype
= fetcharg(ITABFETCH(opcode
), i
);
dotp
->e_xvalue
+= ap
->a_dispsize
;
if ((xp
->e_xtype
&XTYPE
)!=XABS
|| xp
->e_xtype
&XFORW
){
dotp
->e_xvalue
+= ap
->a_dispsize
;
if (xp
->e_xvalue
==0 && !(argtype
&ASTAR
))
if (ISBYTE(xp
->e_xvalue
))
if (ISWORD(xp
->e_xvalue
))
argtype
= fetcharg(ITABFETCH(opcode
), i
);
if (immconstant(ap
->a_xp
, argtype
, &value
))
dotp
->e_xvalue
+= ty_nbyte
[argtype
];
} /*end of the switch on the type*/
} /*end of looping for all arguments*/
switch(opcode
.Op_eopcode
){
panic("Bad escape opcode");
for (i
=0; i
<n
; i
++,ap
++) {/* now for the arguments */
{ Outb(0x40 | ap
->a_areg2
); }
argtype
= fetcharg(ITABFETCH(opcode
), i
);
xp
->e_xvalue
- (dotp
->e_xvalue
+ 1);
yywarning("%s: destination label is external",
FETCHNAME(ITABFETCH(opcode
)));
yyerror("%s: Branch too far(%db): try -J flag",
FETCHNAME(ITABFETCH(opcode
)),
ap
->a_areg1
= argtype
= xp
->e_xvalue
yywarning("%s: destination label is external",
FETCHNAME(ITABFETCH(opcode
)));
yyerror("%s: Branch too far(%db): try -J flag",
FETCHNAME(ITABFETCH(opcode
)),
xp
->e_xvalue
= argtype
>>8;
/* reduces to expr(pc) mode */
ap
->a_areg1
|= (0xAF + mod124
[ap
->a_dispsize
]);
reloc_how
= type_124
[ap
->a_dispsize
] + RELOC_PCREL
;
case ADISP
: /* expr(%r) */
if ((xp
->e_xtype
&XTYPE
)!=XABS
|| xp
->e_xtype
&XFORW
){
ap
->a_areg1
+= mod124
[ap
->a_dispsize
];
reloc_how
= type_124
[ap
->a_dispsize
];
if (xp
->e_xvalue
==0 && !(ap
->a_areg1
&0x10)) {
if (ISBYTE(xp
->e_xvalue
))
if (ISWORD(xp
->e_xvalue
))
argtype
= fetcharg(ITABFETCH(opcode
), i
);
if (immconstant(xp
, argtype
, &value
)){
} /*end of the switch on argtype*/
* use the first byte to describe the argument
if (reloc_how
!= TYPNONE
)
} /*end of the for to pick up all arguments*/
* Is xp an immediate constant?
* argtype: how the instruction will interpret the bytes
* xp->e_number.num_tag ("numtype"): the kind of number given
* Use the following table:
* float: TYPF, TYPD, TYPG, TYPH
* float slitflt slitflt slitflt
* Where the table entry implies the predicate to return.
#define IMMFLT 1 /* these flags are not used by anybody (yet) */
int immconstant(xp
, argtype
, valuep
)
if ((xp
->e_xtype
& XTYPE
) != XABS
)
if ((xp
->e_xtype
& XFORW
) != 0)
numtype
= xp
->e_number
.num_tag
;
if (passno
== 2) switch(argtype
){
default: fits
= 0; break;
case TYPB
: fits
= 1; break;
fits
= ISBYTE(xp
->e_xvalue
) || ISUBYTE(xp
->e_xvalue
);
default: fits
= 0; break;
case TYPW
: fits
= 1; break;
fits
= ISWORD(xp
->e_xvalue
) || ISUWORD(xp
->e_xvalue
);
if (numtype
== TYPD
){ /* same format for first 32 bits */
fits
= ty_nbyte
[argtype
] >= ty_nbyte
[numtype
];
yywarning("Immediate constant type %s mismatches instruction type %s",
back
= slitflt(xp
->e_number
, argtype
, valuep
);
back
= ISLIT(xp
->e_xvalue
);