1988-09-15 09:49:22 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
#include "as.h"
|
|
|
|
|
|
|
|
#define DOLLAR '$'
|
|
|
|
#define LEFT '('
|
|
|
|
#define RIGHT ')'
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
/* Een constraint-function */
|
|
|
|
|
|
|
|
const( arg)
|
|
|
|
struct t_operand *arg;
|
|
|
|
{
|
|
|
|
return( arg->type == CONST);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* decode_operand() recognizes the follwing assembly-argumnets:
|
|
|
|
|
|
|
|
$const : CONST
|
|
|
|
register : REGISTER
|
|
|
|
-(register) : AUTO_DEC
|
|
|
|
(register)+ : AUTO_INC
|
|
|
|
(register) : REG_DEF
|
|
|
|
index(register) : IND_REG
|
|
|
|
label+offset : LABEL
|
|
|
|
label[b|f] : L_ILB
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* An assembly instruction has at most 5 arguments.
|
|
|
|
* This is for the time being.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char lab_buf[4][256],
|
|
|
|
ind_buf[4][256],
|
|
|
|
*match(), *lab(), *ind(), *end_arg();
|
|
|
|
|
|
|
|
static int n_index = -1;
|
|
|
|
|
|
|
|
|
|
|
|
process_label( l)
|
|
|
|
char *l;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
process_mnemonic( m)
|
|
|
|
char *m;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
process_operand( arg, op)
|
1988-10-20 14:21:37 +00:00
|
|
|
register char *arg;
|
|
|
|
register struct t_operand *op;
|
1988-09-15 09:49:22 +00:00
|
|
|
{
|
1988-10-20 14:21:37 +00:00
|
|
|
register char *einde;
|
1988-09-15 09:49:22 +00:00
|
|
|
|
|
|
|
if ( n_index == 3)
|
|
|
|
n_index = 0;
|
|
|
|
else
|
|
|
|
n_index++;
|
|
|
|
|
|
|
|
if ( arg[0] == '~' ) {
|
|
|
|
op->type = CONST;
|
|
|
|
op->const = arg+1;
|
|
|
|
}
|
|
|
|
else if ( is_reg( arg, &(op->num)) ) {
|
|
|
|
op->type = REGISTER;
|
|
|
|
}
|
|
|
|
else if ((arg[0]=='-') && (arg[1] == LEFT) &&
|
|
|
|
is_reg( arg+2,&(op->num))) {
|
|
|
|
op->type = AUTO_DEC;
|
|
|
|
}
|
|
|
|
else if( ( arg[0] == LEFT) && is_reg( arg+1, &(op->num))) {
|
|
|
|
arg = match( arg, RIGHT);
|
|
|
|
if ( *(arg+1) == '+')
|
|
|
|
op->type = AUTO_INC;
|
|
|
|
else
|
|
|
|
op->type = REG_DEF;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
einde = end_arg( arg);
|
|
|
|
if ( (*einde == 'b' || *einde == 'f') && isdigit( *(einde-1))) {
|
|
|
|
*einde = '\0';
|
|
|
|
op->type = L_ILB;
|
|
|
|
op->offset = "0";
|
|
|
|
op->lab = arg;
|
|
|
|
}
|
|
|
|
else if ( *einde == RIGHT) {
|
|
|
|
op->type = IND_REG;
|
|
|
|
arg = ind( ind_buf[ n_index], arg);
|
|
|
|
if ( is_reg( arg+1, &(op->num)))
|
|
|
|
op->index = ind_buf[ n_index];
|
|
|
|
else
|
|
|
|
fprint( STDERR, "unknown argtype %s\n", arg);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
op->type = LABEL;
|
|
|
|
arg = lab( lab_buf[ n_index], arg);
|
|
|
|
op->lab = lab_buf[ n_index];
|
|
|
|
if ( *arg == '\0')
|
|
|
|
op->offset = "0";
|
|
|
|
else
|
|
|
|
op->offset = arg+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *ind( buf, str)
|
1988-10-20 14:21:37 +00:00
|
|
|
register char *buf, *str;
|
1988-09-15 09:49:22 +00:00
|
|
|
|
|
|
|
/* Reads the index in front of '(register)'.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
while ( *str != LEFT)
|
|
|
|
*buf++ = *str++;
|
|
|
|
*buf = '\0';
|
|
|
|
return( str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *lab( buf, str)
|
1988-10-20 14:21:37 +00:00
|
|
|
register char *buf, *str;
|
1988-09-15 09:49:22 +00:00
|
|
|
|
|
|
|
/* Reads 'label' in front of '+offset'.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
while ( ( *str != '+') && ( *str != '\0'))
|
|
|
|
*buf++ = *str++;
|
|
|
|
*buf = '\0';
|
|
|
|
while ( isspace( *(buf-1)) ) {
|
|
|
|
*(buf-1) = '\0';
|
|
|
|
buf--;
|
|
|
|
}
|
|
|
|
return( str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int is_reg( str, num)
|
1988-10-20 14:21:37 +00:00
|
|
|
register char *str;
|
|
|
|
register int *num;
|
1988-09-15 09:49:22 +00:00
|
|
|
|
|
|
|
/* Is "str" a 'registers' ?
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
if ( ( *str == 'a') && ( *(str+1) == 'p')) {
|
|
|
|
*num = 12;
|
|
|
|
return( TRUE);
|
|
|
|
}
|
|
|
|
else if ( ( *str == 'f') && ( *(str+1) == 'p')) {
|
|
|
|
*num = 13;
|
|
|
|
return( TRUE);
|
|
|
|
}
|
|
|
|
else if ( ( *str == 's') && ( *(str+1) == 'p')) {
|
|
|
|
*num = 14;
|
|
|
|
return( TRUE);
|
|
|
|
}
|
|
|
|
if ( *str == 'r') {
|
|
|
|
if ( isdigit( *(str+1)) && isdigit( *(str+2))) {
|
|
|
|
*num = ( *(str+1) - '0') * 10 + *(str+2) - '0';
|
|
|
|
return( TRUE);
|
|
|
|
}
|
|
|
|
else if ( isdigit( *(str+1))) {
|
|
|
|
*num = *(str+1) - '0';
|
|
|
|
return( TRUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return( FALSE);
|
|
|
|
}
|
|
|
|
return( FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *end_arg( str)
|
1988-10-20 14:21:37 +00:00
|
|
|
register char *str;
|
1988-09-15 09:49:22 +00:00
|
|
|
|
|
|
|
/* Shift to the last character of "str".
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
while ( *str != '\0')
|
|
|
|
str++;
|
|
|
|
return( str-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *match( str, sym)
|
1988-10-20 14:21:37 +00:00
|
|
|
register char *str;
|
|
|
|
char sym;
|
1988-09-15 09:49:22 +00:00
|
|
|
{
|
|
|
|
while ( *str != sym)
|
|
|
|
str++;
|
|
|
|
return( str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
char my_buf[256];
|
|
|
|
|
|
|
|
gen_operand( op)
|
1988-10-20 14:21:37 +00:00
|
|
|
register struct t_operand *op;
|
1988-09-15 09:49:22 +00:00
|
|
|
|
|
|
|
/* Generate object-code for a argument.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
switch( op->type) {
|
1988-10-20 14:21:37 +00:00
|
|
|
case CONST :
|
|
|
|
if (isdigit(op->const[0])) {
|
|
|
|
long l, atol();
|
|
|
|
l = atol(op->const);
|
|
|
|
if (fit_6bits(l)) {
|
|
|
|
@text1(%$(op->const));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
@text1( 0x8f);
|
|
|
|
@text4( %$(op->const));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
@as_const(%$(op->const));
|
|
|
|
}
|
1988-09-15 09:49:22 +00:00
|
|
|
break;
|
|
|
|
case REGISTER: @text1( %d(0x50 | op->num));
|
|
|
|
break;
|
|
|
|
case REG_DEF : @text1( %d(0x60 | op->num));
|
|
|
|
break;
|
|
|
|
case AUTO_DEC : @text1( %d(0x70 | op->num));
|
|
|
|
break;
|
|
|
|
case AUTO_INC : @text1( %d(0x80 | op->num));
|
|
|
|
break;
|
1988-10-20 14:21:37 +00:00
|
|
|
case IND_REG :
|
|
|
|
if (isdigit(op->index[0])) {
|
|
|
|
long l, atol();
|
|
|
|
l = atol(op->index);
|
|
|
|
if (fit_byte(l)) {
|
|
|
|
@text1( %d(0xa0 | op->num));
|
|
|
|
@text1( %$(op->index));
|
|
|
|
} else if (fit_word(l)) {
|
|
|
|
@text1( %d(0xc0 | op->num));
|
|
|
|
@text2( %$(op->index));
|
|
|
|
} else {
|
|
|
|
@text1( %d(0xe0 | op->num));
|
|
|
|
@text4( %$(op->index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
@as_indexed(%$(op->index) , %d(op->num));
|
|
|
|
}
|
1988-09-15 09:49:22 +00:00
|
|
|
break;
|
|
|
|
case LABEL : @text1( 0xef);
|
|
|
|
if ( strindex( op->lab, DOLLAR)) {
|
|
|
|
@reloc4( %$(op->lab), %$(op->offset), PC_REL);
|
|
|
|
}
|
|
|
|
else if ( strindex( op->lab, LEFT)) {
|
|
|
|
@reloc4( %$(op->lab), %$(op->offset), PC_REL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sprint( my_buf, "\"%s\"", op->lab);
|
|
|
|
@reloc4( %$(my_buf), %$(op->offset) , PC_REL);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case L_ILB : @text1( %dist( op->lab));
|
|
|
|
break;
|
|
|
|
default : fprint( STDERR, "error");
|
|
|
|
}
|
|
|
|
}
|