OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [AS64/] [source/] [FISA64.cpp] - Rev 48

Compare with Previous | Blame | View Log

// ============================================================================
//        __
//   \\__/ o\    (C) 2014  Robert Finch, Stratford
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
// A64 - Assembler
//  - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify 
// it under the terms of the GNU Lesser General Public License as published 
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
//                                                                          
// This source file is distributed in the hope that it will be useful,      
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// GNU General Public License for more details.                             
//                                                                          
// You should have received a copy of the GNU General Public License        
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
//                                                                          
// ============================================================================
//
#include "stdafx.h"
 
#define BCC(x)       (((x) << 12)|0x38)
 
// Fixup types
#define FUT_C15       1
#define FUT_C40       2
#define FUT_C64       3
#define FUT_R27       4
 
 
static void emitAlignedCode(int cd);
static void process_shifti(int oc);
static void ProcessEOL(int opt);
 
extern int first_rodata;
extern int first_data;
extern int first_bss;
static int64_t ca;
extern int isInitializationData;
extern int use_gp;
 
// This structure not used.
typedef struct tagInsn
{
    union {
        struct {
            unsigned int opcode : 7;
            unsigned int Ra : 5;
            unsigned int Rt : 5;
            unsigned int imm : 15;
        } ri;
        struct {
            unsigned int opcode : 7;
            unsigned int Ra : 5;
            unsigned int Rt : 5;
            unsigned int Rb : 5;
            unsigned int resv : 3;
            unsigned int funct : 7;
        } rr;
    };
};
 
// ----------------------------------------------------------------------------
// Return the register number or -1 if not a register.
// Parses pretty register names like SP or BP in addition to r1,r2,etc.
// ----------------------------------------------------------------------------
 
static int getRegisterX()
{
    int reg;
 
    while(isspace(*inptr)) inptr++;
    switch(*inptr) {
    case 'r': case 'R':
         if (isdigit(inptr[1])) {
             reg = inptr[1]-'0';
             if (isdigit(inptr[2])) {
                 reg = 10 * reg + (inptr[2]-'0');
                 if (isdigit(inptr[3])) {
                     reg = 10 * reg + (inptr[3]-'0');
                     if (isIdentChar(inptr[4]))
                         return -1;
                     inptr += 4;
                     NextToken();
                     return reg;
                 }
                 else if (isIdentChar(inptr[3]))
                     return -1;
                 else {
                     inptr += 3;
                     NextToken();
                     return reg;
                 }
             }
             else if (isIdentChar(inptr[2]))
                 return -1;
             else {
                 inptr += 2;
                 NextToken();
                 return reg;
             }
         }
         else return -1;
    case 'b': case 'B':
        if ((inptr[1]=='P' || inptr[1]=='p') && !isIdentChar(inptr[2])) {
            inptr += 2;
            NextToken();
            return 27;
        }
        break;
    case 'g': case 'G':
        if ((inptr[1]=='P' || inptr[1]=='p') && !isIdentChar(inptr[2])) {
            inptr += 2;
            NextToken();
            return 26;
        }
        break;
    case 's': case 'S':
        if ((inptr[1]=='P' || inptr[1]=='p') && !isIdentChar(inptr[2])) {
            inptr += 2;
            NextToken();
            return 30;
        }
        break;
    case 't': case 'T':
        if ((inptr[1]=='P' || inptr[1]=='p') && !isIdentChar(inptr[2])) {
            inptr += 2;
            NextToken();
            return 25;
        }
        if ((inptr[1]=='R' || inptr[1]=='r') && !isIdentChar(inptr[2])) {
            inptr += 2;
            NextToken();
            return 24;
        }
        break;
    case 'p': case 'P':
        if ((inptr[1]=='c' || inptr[1]=='C') && !isIdentChar(inptr[2])) {
            inptr += 2;
            NextToken();
            return 29;
        }
        break;
    case 'l': case 'L':
        if ((inptr[1]=='R' || inptr[1]=='r') && !isIdentChar(inptr[2])) {
            inptr += 2;
            NextToken();
            return 31;
        }
        break;
    case 'x': case 'X':
        if ((inptr[1]=='l' || inptr[1]=='L') && (inptr[2]=='r' || inptr[2]=='R') &&
        !isIdentChar(inptr[3])) {
            inptr += 3;
            NextToken();
            return 28;
        }
        break;
    default:
        return -1;
    }
    return -1;
}
 
 
static int getBoundsRegister()
{
    int reg;
 
    while(isspace(*inptr)) inptr++;
    switch(*inptr) {
    case 'b': case 'B':
         if (isdigit(inptr[1])) {
             reg = inptr[1]-'0';
             if (isdigit(inptr[2])) {
                 reg = 10 * reg + (inptr[2]-'0');
                 if (isdigit(inptr[3])) {
                     reg = 10 * reg + (inptr[3]-'0');
                     if (isIdentChar(inptr[4]))
                         return -1;
                     inptr += 4;
                     NextToken();
                     return reg;
                 }
                 else if (isIdentChar(inptr[3]))
                     return -1;
                 else {
                     inptr += 3;
                     NextToken();
                     return reg;
                 }
             }
             else if (isIdentChar(inptr[2]))
                 return -1;
             else {
                 inptr += 2;
                 NextToken();
                 return reg;
             }
         }
         else return -1;
    }
    return -1;
}
 
 
// ----------------------------------------------------------------------------
// Get the friendly name of a special purpose register.
// ----------------------------------------------------------------------------
 
static int FISA64_getSprRegister()
{
    while(isspace(*inptr)) inptr++;
    switch(*inptr) {
 
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
         NextToken();
         NextToken();
         return (int)ival.low;
 
    // bear
    case 'b': case 'B':
         if ((inptr[1]=='e' || inptr[1]=='E') &&
             (inptr[2]=='a' || inptr[2]=='A') &&
             (inptr[3]=='r' || inptr[3]=='R') &&
             !isIdentChar(inptr[4])) {
             inptr += 4;
             NextToken();
             return 11;
         }
         break;
    // cas clk cr0 cr3
    case 'c': case 'C':
         if ((inptr[1]=='a' || inptr[1]=='A') &&
             (inptr[2]=='s' || inptr[2]=='S') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 44;
         }
         if ((inptr[1]=='l' || inptr[1]=='L') &&
             (inptr[2]=='k' || inptr[2]=='K') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 0x06;
         }
         if ((inptr[1]=='r' || inptr[1]=='R') &&
             (inptr[2]=='0') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 0x00;
         }
         if ((inptr[1]=='r' || inptr[1]=='R') &&
             (inptr[2]=='3') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 0x03;
         }
         break;
 
    // dbad0 dbad1 dbctrl dpc dsp
    case 'd': case 'D':
         if ((inptr[1]=='b' || inptr[1]=='B') &&
             (inptr[2]=='a' || inptr[2]=='A') &&
             (inptr[3]=='d' || inptr[3]=='D') &&
             (inptr[4]=='0' || inptr[4]=='0') &&
             !isIdentChar(inptr[5])) {
             inptr += 5;
             NextToken();
             return 50;
         }
         if ((inptr[1]=='b' || inptr[1]=='B') &&
             (inptr[2]=='a' || inptr[2]=='A') &&
             (inptr[3]=='d' || inptr[3]=='D') &&
             (inptr[4]=='1' || inptr[4]=='1') &&
             !isIdentChar(inptr[5])) {
             inptr += 5;
             NextToken();
             return 51;
         }
         if ((inptr[1]=='b' || inptr[1]=='B') &&
             (inptr[2]=='a' || inptr[2]=='A') &&
             (inptr[3]=='d' || inptr[3]=='D') &&
             (inptr[4]=='2' || inptr[4]=='2') &&
             !isIdentChar(inptr[5])) {
             inptr += 5;
             NextToken();
             return 52;
         }
         if ((inptr[1]=='b' || inptr[1]=='B') &&
             (inptr[2]=='a' || inptr[2]=='A') &&
             (inptr[3]=='d' || inptr[3]=='D') &&
             (inptr[4]=='3' || inptr[4]=='3') &&
             !isIdentChar(inptr[5])) {
             inptr += 5;
             NextToken();
             return 53;
         }
         if ((inptr[1]=='b' || inptr[1]=='B') &&
             (inptr[2]=='c' || inptr[2]=='C') &&
             (inptr[3]=='t' || inptr[3]=='T') &&
             (inptr[4]=='r' || inptr[4]=='R') &&
             (inptr[5]=='l' || inptr[5]=='L') &&
             !isIdentChar(inptr[6])) {
             inptr += 6;
             NextToken();
             return 54;
         }
         if ((inptr[1]=='p' || inptr[1]=='P') &&
             (inptr[2]=='c' || inptr[2]=='C') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 7;
         }
         if (
             (inptr[1]=='b' || inptr[1]=='B') &&
             (inptr[2]=='p' || inptr[2]=='P') &&
             (inptr[3]=='c' || inptr[3]=='C') &&
             !isIdentChar(inptr[4])) {
             inptr += 4;
             NextToken();
             return 7;
         }
         if ((inptr[1]=='s' || inptr[1]=='S') &&
             (inptr[2]=='p' || inptr[2]=='P') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 16;
         }
         break;
 
    // ea epc esp
    case 'e': case 'E':
         if ((inptr[1]=='a' || inptr[1]=='A') &&
             !isIdentChar(inptr[2])) {
             inptr += 2;
             NextToken();
             return 40;
         }
         if ((inptr[1]=='p' || inptr[1]=='P') &&
             (inptr[2]=='c' || inptr[2]=='C') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 9;
         }
         if ((inptr[1]=='s' || inptr[1]=='S') &&
             (inptr[2]=='p' || inptr[2]=='P') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 17;
         }
         break;
 
    // fault_pc
    case 'f': case 'F':
         if ((inptr[1]=='a' || inptr[1]=='A') &&
             (inptr[2]=='u' || inptr[2]=='U') &&
             (inptr[3]=='l' || inptr[3]=='L') &&
             (inptr[4]=='t' || inptr[4]=='T') &&
             (inptr[5]=='_' || inptr[5]=='_') &&
             (inptr[6]=='p' || inptr[6]=='P') &&
             (inptr[7]=='c' || inptr[7]=='C') &&
             !isIdentChar(inptr[8])) {
             inptr += 8;
             NextToken();
             return 0x08;
         }
         break;
 
    // history
    case 'h': case 'H':
         if ((inptr[1]=='i' || inptr[1]=='I') &&
             (inptr[2]=='s' || inptr[2]=='S') &&
             (inptr[3]=='t' || inptr[3]=='T') &&
             (inptr[4]=='o' || inptr[4]=='O') &&
             (inptr[5]=='r' || inptr[5]=='R') &&
             (inptr[6]=='y' || inptr[6]=='Y') &&
             !isIdentChar(inptr[7])) {
             inptr += 7;
             NextToken();
             return 0x0D;
         }
         break;
 
    // ipc isp ivno
    case 'i': case 'I':
         if ((inptr[1]=='p' || inptr[1]=='P') &&
             (inptr[2]=='c' || inptr[2]=='C') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 8;
         }
         if ((inptr[1]=='s' || inptr[1]=='S') &&
             (inptr[2]=='p' || inptr[2]=='P') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 15;
         }
         if ((inptr[1]=='v' || inptr[1]=='V') &&
             (inptr[2]=='n' || inptr[2]=='N') &&
             (inptr[3]=='o' || inptr[3]=='O') &&
             !isIdentChar(inptr[4])) {
             inptr += 4;
             NextToken();
             return 0x0C;
         }
         break;
 
 
    // LOTGRP
    case 'l': case 'L':
         if ((inptr[1]=='o' || inptr[1]=='O') &&
             (inptr[2]=='t' || inptr[2]=='T') &&
             (inptr[3]=='g' || inptr[3]=='G') &&
             (inptr[4]=='r' || inptr[4]=='R') &&
             (inptr[5]=='p' || inptr[5]=='P') &&
             !isIdentChar(inptr[6])) {
             inptr += 6;
             NextToken();
             return 42;
         }
         break;
 
    // rand
    case 'r': case 'R':
         if ((inptr[1]=='a' || inptr[1]=='A') &&
             (inptr[2]=='n' || inptr[2]=='N') &&
             (inptr[3]=='d' || inptr[3]=='D') &&
             !isIdentChar(inptr[4])) {
             inptr += 4;
             NextToken();
             return 0x12;
         }
         break;
    // ss_ll srand1 srand2
    case 's': case 'S':
         if ((inptr[1]=='s' || inptr[1]=='S') &&
             (inptr[2]=='_' || inptr[2]=='_') &&
             (inptr[3]=='l' || inptr[3]=='L') &&
             (inptr[4]=='l' || inptr[4]=='L') &&
             !isIdentChar(inptr[5])) {
             inptr += 5;
             NextToken();
             return 0x1A;
         }
         if ((inptr[1]=='r' || inptr[1]=='R') &&
             (inptr[2]=='a' || inptr[2]=='A') &&
             (inptr[3]=='n' || inptr[3]=='N') &&
             (inptr[4]=='d' || inptr[4]=='D') &&
             (inptr[5]=='1') &&
             !isIdentChar(inptr[6])) {
             inptr += 6;
             NextToken();
             return 0x10;
         }
         if ((inptr[1]=='r' || inptr[1]=='R') &&
             (inptr[2]=='a' || inptr[2]=='A') &&
             (inptr[3]=='n' || inptr[3]=='N') &&
             (inptr[4]=='d' || inptr[4]=='D') &&
             (inptr[5]=='2') &&
             !isIdentChar(inptr[6])) {
             inptr += 6;
             NextToken();
             return 0x11;
         }
         if ((inptr[1]=='p' || inptr[1]=='P') &&
             (inptr[2]=='r' || inptr[2]=='R') &&
             isdigit(inptr[3]) && isdigit(inptr[4]) &&
             !isIdentChar(inptr[5])) {
             inptr += 5;
             NextToken();
             return (inptr[3]-'0')*10 + (inptr[4]-'0');
         }
         break;
 
    // tag tick 
    case 't': case 'T':
         if ((inptr[1]=='i' || inptr[1]=='I') &&
             (inptr[2]=='c' || inptr[2]=='C') &&
             (inptr[3]=='k' || inptr[3]=='K') &&
             !isIdentChar(inptr[4])) {
             inptr += 4;
             NextToken();
             return 4;
         }
         if ((inptr[1]=='a' || inptr[1]=='A') &&
             (inptr[2]=='g' || inptr[2]=='G') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 41;
         }
         break;
 
    // vbr
    case 'v': case 'V':
         if ((inptr[1]=='b' || inptr[1]=='B') &&
             (inptr[2]=='r' || inptr[2]=='R') &&
             !isIdentChar(inptr[3])) {
             inptr += 3;
             NextToken();
             return 10;
         }
         break;
    }
    return -1;
}
 
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
 
static void emit_insn(int64_t oc)
{
     emitAlignedCode(oc & 255);
     emitCode((oc >> 8) & 255);
     emitCode((oc >> 16) & 255);
     emitCode((oc >> 24) & 255);
     num_bytes += 4;
     num_insns += 1;
}
 
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
 
static void emit_insn2(int64_t oc)
{
     emitCode(oc & 255);
     emitCode((oc >> 8) & 255);
     emitCode((oc >> 16) & 255);
     emitCode((oc >> 24) & 255);
     num_bytes += 4;
     num_insns += 1;
}
 
 
static void emit2(int64_t oc)
{
     emitAlignedCode(oc & 255);
     emitCode((oc >> 8) & 255);
     num_bytes += 2;
     num_insns += 1;
}
 
static void emit6(int64_t oc)
{
     emitAlignedCode(oc & 255);
     emitCode((oc >> 8) & 255);
     emitCode((oc >> 16) & 255);
     emitCode((oc >> 24) & 255);
     emitCode((oc >> 32) & 255);
     emitCode((oc >> 40) & 255);
     num_bytes += 6;
     num_insns += 1;
}
 
// ---------------------------------------------------------------------------
// Emit code aligned to a code address.
// ---------------------------------------------------------------------------
 
static void emitAlignedCode(int cd)
{
     int64_t ad;
 
 
     ad = code_address & 15;
     while (ad != 0 && ad != 2 && ad != 4 && ad != 6 &&
            ad != 8 && ad != 10 && ad != 12 && ad != 14) {
         emitByte(0x00);
         ad = code_address & 15;
     }
 
     emitByte(cd);
}
 
 
// ---------------------------------------------------------------------------
// Determine how big of a prefix is required.
// ---------------------------------------------------------------------------
 
static int fitsIn0(int64_t v)
{
    return (((v < 0) && ((v >> 14) == -1L)) || ((v >= 0) && ((v >> 14) == 0)));
}
 
static int fitsIn10(int64_t v)
{
    return (((v < 0) && ((v >> 24) == -1L)) || ((v >= 0) && ((v >> 24) == 0)));
}
 
static int fitsIn28(int64_t v)
{
    return (((v < 0) && ((v >> 42) == -1L)) || ((v >= 0) && ((v >> 42) == 0)));
}
 
static int fitsIn41(int64_t v)
{
    return (((v < 0) && ((v >> 55) == -1L)) || ((v >= 0) && ((v >> 55) == 0)));
}
// ---------------------------------------------------------------------------
// Emit constant extension for 15-bit operands.
// Returns number of constant prefixes placed.
// ---------------------------------------------------------------------------
 
static int emitImm15(int64_t v, int force)
{
     int nn;
 
     if (fitsIn0(v))
        return 0;
     else if (fitsIn10(v)) {
         emit2(
            ((v >> 16) << 7) | ((v>>15) & 1) |
            0x10
         );
         return 1;
     }
     else if (fitsIn28(v)) {
         emit_insn(0x78|(((v >> 18)&0x1FFFFFFLL) << 7)|((v >> 15)&7));
         return 1;
     }
     else if (fitsIn41(v)) {
         emit6(0x13|((v >> 15)&0x1FFFFFFFFFFLL) << 7);
         return 1;
     }
     else {
         emit_insn(0x78|(((v >> 46)&0x3FFFFLL) << 7)|((v >> 43)&7));
         emit_insn(0x78|(((v >> 18)&0x1FFFFFFLL) << 7)|((v >> 15)&7));
         return 2;
     }
 
     // ToDo: modify the fixup record type based on the number of prefixes emitted.
    if (bGen && lastsym && !use_gp && (lastsym->isExtern || lastsym->defined==0))
    if( lastsym->segment < 5)
    sections[segment+7].AddRel(sections[segment].index,((int64_t)(lastsym->ord+1) << 32) | nn+1 | (lastsym->isExtern ? 128 : 0)|
    (lastsym->segment==codeseg ? code_bits << 8 : data_bits << 8));
     return nn;
}
 
// ---------------------------------------------------------------------------
// bfextu r1,r2,#1,#63
// ---------------------------------------------------------------------------
 
static void process_bitfield(int oc)
{
    int Ra;
    int Rt;
    int mb;
    int me;
 
    Rt = getRegisterX();
    need(',');
    Ra = getRegisterX();
    need(',');
    NextToken();
    mb = (int)expr();
    need(',');
    NextToken();
    me = (int)expr();
    emit_insn(
        (oc << 29) |
        (me << 23) |
        (mb << 17) |
        (Rt << 12) |
        (Ra << 7) |
        0x03          // bitfield
    );
}
 
// ---------------------------------------------------------------------------
// sys 4
// ---------------------------------------------------------------------------
 
static void process_brk(int oc)
{
    int val;
 
    NextToken();
    val = (int)expr();
    emit_insn(
        (oc << 30) |
        ((val & 0x1ff) << 17) |
        (30 << 7) |
        0x38
    );
}
 
// ----------------------------------------------------------------------------
// chk r1,r2,b32
// ----------------------------------------------------------------------------
 
static void process_chk(int oc)
{
     int Ra;
     int Br;
     int Rt;
 
     Rt = getRegisterX();
     need(',');
     Ra = getRegisterX();
     need(',');
     Br = getBoundsRegister();
     emit_insn(
         (oc << 25) |
         (Br << 17) |
         (Rt << 12) |
         (Ra << 7) |
         0x02
     );
     prevToken();
}
 
// ---------------------------------------------------------------------------
// COM is an alternate mnemonic for EOR Rt,Ra,#-1
// com r3,r3
// ---------------------------------------------------------------------------
 
static void process_com()
{
    int Ra;
    int Rt;
 
    Rt = getRegister();
    need(',');
    Ra = getRegister();
    prevToken();
    emit_insn(
        (0x7fff << 17) |
        (Rt << 12) |
        (Ra << 7) |
        0x0e           // EOR
    );
}
 
// ----------------------------------------------------------------------------
// cpuid r1,r2,#0
// ----------------------------------------------------------------------------
 
static void process_cpuid(int oc)
{
     int Ra;
     int Rt;
     int val;
 
     Rt = getRegisterX();
     need(',');
     Ra = getRegisterX();
     need(',');
     NextToken();
     val = (int)expr();
     emit_insn(
         (oc << 25) | 
         ((val & 15) << 17) |
         (Rt << 12) |
         (Ra << 7) |
         0x02
     );
     prevToken();
}
 
// ---------------------------------------------------------------------------
// JAL also processes JMP and JSR
// jal r0,main
// jal r0,[r19]
// jmp (tbl,r2)
// ---------------------------------------------------------------------------
 
static void process_jal(int oc, int Rt)
{
    int64_t addr;
    int Ra;
 
    // -1 indicates to parse a target register
    if (Rt == -1) {
        Rt = getRegisterX();
        if (Rt==-1) {
            printf("Expecting a target register.");
            return ;
        }
        need(',');
    }
    NextToken();
    // Memory indirect ?
    if (token=='(' || token=='[') {
       Ra = getRegisterX();
       if (Ra==-1) {
           Ra = 0;
           NextToken();
           addr = expr();
           prevToken();
           if (token==',') {
               NextToken();
               Ra = getRegisterX();
               if (Ra==-1) Ra = 0;
           }
           else if (token=='[') {
                NextToken();
               Ra = getRegisterX();
               if (Ra==-1) Ra = 0;
               need(']');
               NextToken();
           }
           if (token!=')' && token != ']')
               printf("Missing close bracket.\r\n");
           emitImm15(addr,lastsym!=(SYM*)NULL);
           emit_insn(
               ((addr & 0x7fffLL) << 17) |
               (Rt << 12) |
               (Ra << 7) | 
               0x3e
           );
           return;
       }
       // Simple [Rn]
       else {
            if (token != ')' && token!=']')
                printf("Missing close bracket\r\n");
            emit_insn(
                (Rt << 12) |
                (Ra << 7) |
                0x3C
            );
            return;
       }
    }
    addr = expr() >> 1;
    prevToken();
    // d(Rn)? 
    if (token=='(' || token=='[') {
        NextToken();
        Ra = getRegisterX();
        if (Ra==-1) {
            printf("Illegal jump address mode.\r\n");
            Ra = 0;
        }
        emitImm15(addr,0);
        emit_insn(
            ((addr & 0x7fffLL) << 17) |
            (Rt << 12) |
            (Ra << 7) | 
            0x3C
        );
        return;
    }
    emitImm15(addr, code_bits > 32);
    emit_insn(
        ((addr & 0x7fffLL) << 17) |
        (Rt << 12) |
        0x3C
    );
}
 
// ---------------------------------------------------------------------------
// subi r1,r2,#1234
// ---------------------------------------------------------------------------
 
static void process_riop(int oc)
{
    int Ra;
    int Rt;
    char *p;
    int64_t val;
 
    p = inptr;
    Rt = getRegisterX();
    need(',');
    Ra = getRegisterX();
    need(',');
    NextToken();
    val = expr();
    emitImm15(val,lastsym!=(SYM*)NULL);
    if (oc == 0x14 && Ra==Rt && val >= 0 && val <= 15) {
        emit2(
            ((val & 15) << 12) |
            (Ra << 7) |
            0x22
        );
    }
    else if (oc==0x15 && Ra==30 && Rt==30 && val >=0 && val < 4096 && (val &7)==0) {
        emit2(
            (((val >> 3)&0x1ff) << 7) |
            0x25
        );
    }
    else
        emit_insn(
            ((val & 0x7fff) << 17) |
            (Rt << 12) |
            (Ra << 7) |
            oc
        );
}
 
// ---------------------------------------------------------------------------
// add r1,r2,r12
// ---------------------------------------------------------------------------
 
static void process_rrop(int oc)
{
    int Ra;
    int Rb;
    int Rt;
    char *p;
 
    p = inptr;
    Rt = getRegisterX();
    need(',');
    Ra = getRegisterX();
    need(',');
    NextToken();
    if (token=='#') {
        inptr = p;
        switch(oc & 0x7F) {
        case 4: process_riop(4); return;  // add
        case 5: process_riop(5); return;  // sub
        case 6: process_riop(6); return;  // cmp
        case 7: process_riop(7); return;  // mul
        case 8: process_riop(8); return;  // div
        case 9: process_riop(9); return;  // mod
        case 12: process_riop(12); return;  // and
        case 13: process_riop(13); return;  // or
        case 14: process_riop(14); return;  // eor
        case 0x14: process_riop(0x14); return;  // addu
        case 0x15: process_riop(0x15); return;  // subu
        case 0x16: process_riop(0x16); return;  // cmpu
        case 0x17: process_riop(0x17); return;  // mulu
        case 0x18: process_riop(0x18); return;  // divu
        case 0x19: process_riop(0x19); return;  // modu
        // Shift
        case 0x30:
        case 0x31:
        case 0x32:
        case 0x33:
        case 0x34:
             process_shifti((oc & 0x7F) + 8); return;
        default:    process_riop(oc); return;
        }
        return;
    }
    prevToken();
    Rb = getRegisterX();
    prevToken();
    emit_insn(
              ((oc & 0x7f) << 25) |
//              ((oc >> 6) << 31) | // for shifts
              (Rb << 17) |
              (Rt << 12) |
              (Ra << 7)|
              2
    );
}
 
// ---------------------------------------------------------------------------
// fabs.d fp1,fp2[,rm]
// ---------------------------------------------------------------------------
 
static void process_fprop(int oc)
{
    int Ra;
    int Rt;
    char *p;
    int  sz;
    int fmt;
    int rm;
 
    rm = 0;
    sz = 'd';
    if (*inptr=='.') {
        inptr++;
        if (strchr("sdtqSDTQ",*inptr)) {
            sz = tolower(*inptr);
            inptr++;
        }
        else
            printf("Illegal float size.\r\n");
    }
    p = inptr;
    if (oc==0x65 || oc==0x66)  // mffp, mv2fix
        Rt = getRegister();
    else
        Rt = getFPRegister();
    need(',');
    if (oc==0x1C || oc==0x1D)  // mtfp, mv2flt
        Ra = getRegister();
    else     
        Ra = getFPRegister();
    if (token==',')
       rm = getFPRoundMode();
    prevToken();
 
    switch(sz) {
    case 's': fmt = 0; break;
    case 'd': fmt = 1; break;
    case 't': fmt = 2; break;
    case 'q': fmt = 3; break;
    }
    emit_insn(
        (oc << 25) |
        (fmt << 20) |
        (rm << 17) |
        (Rt << 12) |
        (Ra << 7) |
        0x02
    );
}
 
// ---------------------------------------------------------------------------
// fadd.d fp1,fp2,fp12[,rm]
// fcmp.d r1,fp3,fp10[,rm]
// ---------------------------------------------------------------------------
 
static void process_fprrop(int oc)
{
    int Ra;
    int Rb;
    int Rt;
    char *p;
    int  sz;
    int fmt;
    int rm;
 
    rm = 0;
    sz = 'd';
    if (*inptr=='.') {
        inptr++;
        if (strchr("sdtqSDTQ",*inptr)) {
            sz = tolower(*inptr);
            inptr++;
        }
        else
            printf("Illegal float size.\r\n");
    }
    p = inptr;
    if (oc==0x2A)        // fcmp
        Rt = getRegister();
    else
        Rt = getFPRegister();
    need(',');
    Ra = getFPRegister();
    need(',');
    Rb = getFPRegister();
    if (token==',')
       rm = getFPRoundMode();
    prevToken();
    switch(sz) {
    case 's': fmt = 0; break;
    case 'd': fmt = 1; break;
    case 't': fmt = 2; break;
    case 'q': fmt = 3; break;
    }
    emit_insn(
        (fmt << 25) |
        (rm << 22) |
        (Rb << 17) |
        (Rt << 12) |
        (Ra << 7) |
        oc
    );
}
 
// ---------------------------------------------------------------------------
// fcx r0,#2
// fdx r1,#0
// ---------------------------------------------------------------------------
 
static void process_fpstat(int oc)
{
    int Ra;
    int64_t bits;
    char *p;
 
    p = inptr;
    bits = 0;
    Ra = getRegister();
    if (token==',') {
       NextToken();
       bits = expr();
    }
    prevToken();
    emitAlignedCode(0x01);
    emitCode(Ra);
    emitCode(bits & 0xff);
    emitCode(0x00);
    emitCode(oc);
}
 
// ---------------------------------------------------------------------------
// not r3,r3
// ---------------------------------------------------------------------------
 
static void process_rop(int oc)
{
    int Ra;
    int Rt;
 
    Rt = getRegister();
    need(',');
    Ra = getRegister();
    prevToken();
    emit_insn(
        (oc << 25) |
        (Rt << 12) |
        (Ra << 7) |
        0x02
    );
}
 
// ---------------------------------------------------------------------------
// beq r1,label
// ---------------------------------------------------------------------------
 
static void process_bcc(int oc)
{
    int Ra;
    int64_t val;
    int64_t disp,disp1;
    int64_t ad;
 
    val = 0;
    Ra = getRegisterX();
    need(',');
    NextToken();
    val = expr();
    ad = code_address;
    disp1 = ((val - ad) >> 1);
    disp = ((val - ad) >> 1) & 0x7fffLL;
 
    if ((oc == 0 || oc==1) && disp1 != 0 && disp1 >= -8 && disp1 <= 7) {
       emit2(
           ((disp & 15) << 12) |
           (Ra << 7) |
           (oc ? 0x33 : 0x32)
       );           
    }
    else
 
        emit_insn(
            (disp << 17) |
            (oc << 12) |
            (Ra << 7) |
            0x3D
        );
}
 
// ---------------------------------------------------------------------------
// bra label
// ---------------------------------------------------------------------------
 
static void process_bra(int oc)
{
    int64_t val;
    int64_t disp,disp1;
    int64_t ad;
 
    val = 0;
    NextToken();
    val = expr();
     // ToDo: modify the fixup record type based on the number of prefixes emitted.
    if (bGen && lastsym && (lastsym->isExtern || lastsym->defined==0))
    if( lastsym->segment < 5)
    sections[segment+7].AddRel(sections[segment].index,((int64_t)(lastsym->ord+1) << 32) | FUT_R27 | (lastsym->isExtern ? 128 : 0)|
    (lastsym->segment==codeseg ? code_bits << 8 : data_bits << 8));
    ad = code_address;
    disp1 = ((val - ad) >> 1);
    disp = ((val - ad) >> 1) & 0x1ffffffLL;
    if (disp1 >= -256 && disp1 <= 255 && disp1 != 0 && oc==0x3A)
       emit2(
            ((disp1 & 0x1ff) << 7) |
            0x23
       );
    else
        emit_insn(
            (disp << 7) |
            (oc & 0x7f)
        );
}
 
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
 
static void getIndexScale(int *sc)
{
      int64_t val;
 
      NextToken();
      val = expr();
      prevToken();
      switch(val) {
      case 0: *sc = 0; break;
      case 1: *sc = 0; break;
      case 2: *sc = 1; break;
      case 4: *sc = 2; break;
      case 8: *sc = 3; break;
      default: printf("Illegal scaling factor.\r\n");
      }
}
 
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
static void process_message()
{
    char buf[200];
    int nn;
 
    while(*inptr != '"' && *inptr != '\n') inptr++;
    if (*inptr=='\n') { NextToken(); return; }
    nn = 0;
    inptr++;
    while (*inptr != '"' && *inptr != '\n' && nn < 197) {
        buf[nn] = *inptr;
        inptr++;
        nn++;
    }
    buf[nn] = '\0';
    strcat_s(buf, sizeof(buf), "\r\n");
    printf(buf);
    ScanToEOL();
}
 
// ---------------------------------------------------------------------------
// expr
// expr[Reg]
// expr[Reg+Reg*sc]
// [Reg]
// [Reg+Reg*sc]
// ---------------------------------------------------------------------------
 
static void mem_operand(int64_t *disp, int *regA, int *regB, int *sc, int *md)
{
     int64_t val;
     int8_t ind;
 
     ind = false;
 
     // chech params
     if (disp == (int64_t *)NULL)
         return;
     if (regA == (int *)NULL)
         return;
     if (regB == (int *)NULL)
         return;
     if (sc==(int *)NULL)
         return;
     if (md==(int *)NULL)
         return;
 
     *disp = 0;
     *regA = -1;
     *regB = -1;
     *sc = 0;
     if (token!='[') {;
          val = expr();
          *disp = val;
     }
     if (token=='[') {
         *regA = getRegisterX();
         // Memory indirect ?
         if (*regA == -1) {
             ind = true;
             prevToken();
             *disp = expr();
             if (token=='[') {
                 *regA = getRegisterX();
                 need(']');
                 if (*regA==-1)
                     printf("expecting a register\r\n");
                 NextToken();
             }
             else
                 *regA = 0;
             need(']');
             NextToken();
             if (token=='[') {
                 *regB = getRegisterX();
                 if (*regB==-1)
                     printf("expecting a register\r\n");
                 if (token=='*')
                     getIndexScale(sc);
                 need(']');
             }
             NextToken();
             if (token=='+') {
                 NextToken();
                 if (token=='+') {
                     *md = 7;
                     return;
                 }
             }
             else if (token=='-') {
                  NextToken();
                  if (token=='-') {
                      *md = 6;
                      return;
                  }
             }
             *md = 5;
             return;
         }
         if (token=='+') {
              *sc = 0;
              *regB = getRegisterX();
              if (*regB == -1) {
                  printf("expecting a register\r\n");
              }
              if (token=='*') {
                  getIndexScale(sc);
              }
         }
         need(']');
         if (token=='+') {
             NextToken();
             if (token=='+') {
                 *md = 3;
                 return;
             }
         }
         else if (token=='-') {
              NextToken();
              if (token=='-') {
                  *md = 2;
                  return;
              }
         }
         *md = 1;
     }
}
 
// ---------------------------------------------------------------------------
// sw disp[r1],r2
// sw [r1+r2],r3
// ----------------------------------------------------------------------------
 
static void process_store(int oc)
{
    int Ra;
    int Rb;
    int Rs;
    int sc;
    int md;
    int64_t disp;
 
    if (oc==0x71)
        Rs = getFPRegister();
    else
        Rs = getRegisterX();
    expect(',');
    mem_operand(&disp, &Ra, &Rb, &sc, &md);
    if (Rs < 0) {
        printf("Expecting a source register.\r\n");
        ScanToEOL();
        return;
    }
    if (Rb > 0) {
       if (disp < 0)
           printf("store offset must be greater than zero.\r\n");
       if (disp > 255LL)
           printf("store offset too large.\r\n");
        emit_insn(
            ((disp & 0xff) << 24) |
            (sc << 22) |
            (Rb << 17) |
            (Rs << 12) |
            (Ra << 7) |
            (oc==0x71 ? 0x75 : oc+8)
        );
       return;
    }
    emitImm15(disp,lastsym!=(SYM*)NULL);
    if (Ra < 0) Ra = 0;
    // Convert SW Rn,D[BP] to short form
    if (oc==0x63 && Ra==27 && ((disp & 0x7)==0) && ((disp >> 3) >= -8) && ((disp >> 3) <= 7)) {
        emit2(
           (((disp >> 3) & 0x0f) << 12) |
           (Rs << 7) |
           0x67
        );
    }
    else
        emit_insn(
            ((disp & 0x7fff) << 17) |
            (Rs << 12) |
            (Ra << 7) |
            oc
        );
    ScanToEOL();
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
static void process_ldi(int oc)
{
    int Rt;
    int64_t val;
 
    Rt = getRegisterX();
    if (Rt==-1) {
        Rt = getFPRegister();
        oc = 0x1A;
    }
    expect(',');
    val = expr();
    emitImm15(val,lastsym!=(SYM*)NULL);
 
    if (val <= 7 && val >= -8)
       emit2(
           ((val & 15) << 12) |
           (Rt << 7) |
           0x34
       );
    else
 
        emit_insn(
            ((val & 0x7FFFLL) << 17) |
            (Rt << 12) |
            oc
        );
}
 
// ----------------------------------------------------------------------------
// lw r1,disp[r2]
// lw r1,[r2+r3]
// cas r2,disp[r1]
// ----------------------------------------------------------------------------
 
static void process_load(int oc)
{
    int Ra;
    int Rb;
    int Rt;
    int sc;
    int md;
    char *p;
    int64_t disp;
    int fixup = 5;
 
    sc = 0;
    p = inptr;
    if (oc==0x51)
       Rt = getFPRegister();
    else
        Rt = getRegisterX();
    if (Rt < 0) {
        printf("Expecting a target register.\r\n");
//        printf("Line:%.60s\r\n",p);
        ScanToEOL();
        inptr-=2;
        return;
    }
    expect(',');
    mem_operand(&disp, &Ra, &Rb, &sc, &md);
    if (Rb >= 0) {
       if (disp < 0)
           printf("load offset must be greater than zero.\r\n");
       if (disp > 255LL)
           printf("load offset too large.\r\n");
       fixup = 11;
       if (oc==0x87 || oc==0x6c) {  //LWS CAS
          printf("Address mode not supported.\r\n");
          return;
       }
       if (oc==0x9F) oc = 0x8F;  // LEA
       else oc = oc + 8;
        emit_insn(
            ((disp & 0xff) << 24) |
            (sc << 22) |
            (Rb << 17) |
            (Rt << 12) |
            (Ra << 7) |
            oc
        );
       return;
    }
    emitImm15(disp,lastsym!=(SYM*)NULL);
    if (Ra < 0) Ra = 0;
    // Convert LW Rn,D[BP] to short form
    if (oc==0x46 && Ra==27 && ((disp & 0x7)==0) && ((disp >> 3) >= -8) && ((disp >> 3) <= 7)) {
        emit2(
           (((disp >> 3) & 0x0f) << 12) |
           (Rt << 7) |
           0x5F
        );
    }
    else
        emit_insn(
            ((disp & 0x7ffff) << 17) |
            (Rt << 12) |
            (Ra << 7) |
            oc
        );
    ScanToEOL();
}
 
// ----------------------------------------------------------------------------
// inc -8[bp],#1
// ----------------------------------------------------------------------------
 
static void process_inc(int oc)
{
    int Ra;
    int Rb;
    int sc;
    int sg;
    int64_t incamt;
    int64_t disp;
    char *p;
    int fixup = 5;
    int neg = 0;
 
    NextToken();
    p = inptr;
    mem_operand(&disp, &Ra, &Rb, &sc, &sg);
    incamt = 1;
    if (token==']')
       NextToken();
    if (token==',') {
        NextToken();
        incamt = expr();
        prevToken();
    }
    if (Rb >= 0) {
       if (disp < 0)
           printf("inc offset must be greater than zero.\r\n");
       if (disp > 255LL)
           printf("inc offset too large.\r\n");
       oc = 0x6F;  // INCX
       emit_insn(
           ((disp & 0xFF) << 24) |
           (sc << 22) |
           (Rb << 17) |
           ((incamt & 0x1F) << 12) |
           (Ra << 7) |
           oc
       );
       return;
    }
    if (oc==0x65) neg = 1;
    oc = 0x64;        // INC
    emitImm15(disp,lastsym!=(SYM*)NULL);
    if (Ra < 0) Ra = 0;
    if (neg) incamt = -incamt;
    emit_insn(
        ((disp & 0x7FFF) << 17) |
        ((incamt & 0x1F) << 12) |
        (Ra << 7) |
        oc
    );
    ScanToEOL();
}
 
// ----------------------------------------------------------------------------
// pea disp[r2]
// pea [r2+r3]
// ----------------------------------------------------------------------------
 
static void process_pea()
{
    int oc;
    int Ra;
    int Rb;
    int sc;
    int sg;
    char *p;
    int64_t disp;
    int fixup = 5;
 
    p = inptr;
    NextToken();
    mem_operand(&disp, &Ra, &Rb, &sc, &sg);
    if (Rb >= 0) {
       // For now PEAX isn't supported
       printf("PEA: Illegal address mode.\r\n");
       return;
       fixup = 11;
       oc = 0xB9;  // PEAX
        if (bGen && lastsym && Ra != 249 && !use_gp)
        if( lastsym->segment < 5)
        sections[segment+7].AddRel(sections[segment].index,((int64_t)(lastsym->ord+1) << 32) | fixup | (lastsym->isExtern ? 128 : 0)|
        (lastsym->segment==codeseg ? code_bits << 8 : data_bits << 8));
       emitCode(Ra);
       emitCode(Rb);
       emitCode(0x00);
       emitCode(sc | ((sg & 15) << 2));
       return;
    }
    oc = 0x65;        // PEA
    emitImm15(disp,lastsym!=(SYM*)NULL);
    if (Ra < 0) Ra = 0;
    emit_insn(
        ((disp & 0x7FFFLL) << 17) |
        (0x1E << 12) |
        (Ra << 7) |
        oc
    );
    ScanToEOL();
}
 
 
// ----------------------------------------------------------------------------
// push r1
// push #123
// push -8[BP]
// ----------------------------------------------------------------------------
 
static void process_pushpop(int oc)
{
    int Ra,Rb;
    int64_t val;
    int64_t disp;
    int sc;
    int sg;
 
    Ra = -1;
    Rb = -1;
    NextToken();
    if (token=='#' && oc==0x67) {  // Filter to PUSH
       val = expr();
       emitImm15(val,(code_bits > 32 || data_bits > 32) && lastsym!=(SYM *)NULL);
        emit_insn(
            ((val & 0x7FFFLL) << 17) |
            (0x1E << 12) |
            (0x00 << 7) |
            0x65   // PEA
        );
        return;
    }
    prevToken();
    Ra = getRegisterX();
    if (Ra == -1) {
        NextToken();
        mem_operand(&disp, &Ra, &Rb, &sc, &sg);
        emitImm15(disp,(code_bits > 32 || data_bits > 32) && lastsym!=(SYM *)NULL);
        if (Ra==-1) Ra = 0;
        emit_insn(
            ((disp & 0x7FFFLL) << 17) |
            (0x1E << 12) |
            (Ra << 7) |
            0x66
        );
        ScanToEOL();
        return;
    }
    if (oc==0x57) { // POP
 
        emit2(
           (2 << 12) |
           (Ra << 7) |
           0x31
        );
/*
 
        emit_insn(
            (8 << 17) |
            (Ra << 12) |
            (0x1E << 7) |
            oc
        );
*/
        prevToken();
        return;
    }
    //PUSH
 
    emit2(
       (Ra << 7) |
       0x31
    );
/*
    emit_insn(
        (0x1E << 12) |
        (Ra << 7)
        | oc
    );
*/
    prevToken();
}
 
// ----------------------------------------------------------------------------
// mov r1,r2
// ----------------------------------------------------------------------------
 
static void process_mov()
{
     int Ra;
     int Rt;
 
     Rt = getRegisterX();
     need(',');
     Ra = getRegisterX();
     emit2(
           ((Rt & 0xf) << 12) |
           (Ra << 7) |
           0x20 | ((Rt >> 4) & 1)
     );
/*
     emit_insn(
         (0x0D << 25) | // OR
         (Rt << 12) |
         (Ra << 7) |
         0x02
     );
*/
     prevToken();
}
 
// ----------------------------------------------------------------------------
// neg r1,r2
// ----------------------------------------------------------------------------
 
static void process_neg(int oc)
{
     int Ra;
     int Rb;
     int Rt;
 
     Ra = 0;
     Rt = getRegisterX();
     need(',');
     Rb = getRegisterX();
     emit_insn(
         (oc << 25) | // SUBU
         (Rb << 17) |
         (Rt << 12) |
         (Ra << 7) |
         0x02
     );
     prevToken();
}
 
// ----------------------------------------------------------------------------
// sei
// cli
// rtd
// rte
// rti
// ----------------------------------------------------------------------------
 
static void process_pctrl(int oc)
{
     int Rt;
 
     if (oc==29 || oc==30 || oc==31)
         Rt = 30;
     else
         Rt = 0;
     emit_insn(
         (0x37 << 25) |
         (oc << 17) |
         (Rt << 12) |
         0x02
     );
}
 
// ----------------------------------------------------------------------------
// rts
// rts #24
// rtl
// ----------------------------------------------------------------------------
 
static void process_rts(int oc)
{
     int64_t val;
 
     val = oc==0x3B ? 8 :0;
     NextToken();
     if (token=='#') {
        val = expr();
     }
     emitImm15(val,(code_bits > 32 || data_bits > 32) && lastsym!=(SYM *)NULL);
     if (val < 4096)
         emit2(
             (((val>>3) & 0x1FFLL) << 7) |
             ((oc==0x27) ? 0x37 : 0x30)
         );
     else
         emit_insn(
             ((val & 0x7FFFLL) << 17) |
             (0x1F << 12) |
             (0x1E << 7) |
             oc
         );
}
 
// ----------------------------------------------------------------------------
// asli r1,r2,#5
// ----------------------------------------------------------------------------
 
static void process_shifti(int oc)
{
     int Ra;
     int Rt;
     int64_t val;
 
     Rt = getRegisterX();
     need(',');
     Ra = getRegisterX();
     need(',');
     NextToken();
     val = expr();
     emit_insn(
         (oc << 25) |      
         ((val & 63) << 17) |
         (Rt << 12) |
         (Ra << 7) |
         0x02
     );
}
 
// ----------------------------------------------------------------------------
// gran r1
// ----------------------------------------------------------------------------
 
static void process_gran(int oc)
{
    int Rt;
 
    Rt = getRegisterX();
    emitAlignedCode(0x01);
    emitCode(0x00);
    emitCode(Rt);
    emitCode(0x00);
    emitCode(oc);
    prevToken();
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
static void process_mtspr(int oc)
{
    int spr;
    int Ra;
    int Rc;
 
    Rc = getRegisterX();
    if (Rc==-1) {
        Rc = 0;
        spr = FISA64_getSprRegister();
        if (spr==-1) {
            printf("Line %d: An SPR is needed.\r\n", lineno);
            return;
        }  
    }
    else
       spr = 0;
    need(',');
    Ra = getRegisterX();
    emit_insn(
        (oc << 25) |
        (spr << 17) |
        (Rc << 12) |
        (Ra << 7) |
        0x02
    );
    if (Ra >= 0)
    prevToken();
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
static void process_mtfp(int oc)
{
    int fpr;
    int Ra;
 
    fpr = getFPRegister();
    need(',');
    Ra = getRegisterX();
    emitAlignedCode(0x01);
    emitCode(Ra);
    emitCode(fpr);
    emitCode(0x00);
    emitCode(oc);
    if (Ra >= 0)
    prevToken();
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
static void process_mfspr(int oc)
{
    int spr;
    int Rt;
    int Ra;
 
    Rt = getRegisterX();
    need(',');
    Ra = getRegisterX();
    if (Ra==-1) {
        Ra = 0;
        spr = FISA64_getSprRegister();
        if (spr==-1) {
            printf("An SPR is needed.\r\n");
            return;
        }  
    }
    else
        spr = 0;
    emit_insn(
        (oc << 25) |
        (spr << 17) |
        (Rt << 12) |
        (Ra << 7) |
        0x02
    );
    if (spr >= 0)
    prevToken();
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
static void process_mffp(int oc)
{
    int fpr;
    int Rt;
 
    Rt = getRegisterX();
    need(',');
    fpr = getFPRegister();
    emitAlignedCode(0x01);
    emitCode(fpr);
    emitCode(Rt);
    emitCode(0x00);
    emitCode(oc);
    if (fpr >= 0)
    prevToken();
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
static void process_fprdstat(int oc)
{
    int Rt;
 
    Rt = getRegisterX();
    emitAlignedCode(0x01);
    emitCode(0x00);
    emitCode(Rt);
    emitCode(0x00);
    emitCode(oc);
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
static void ProcessEOL(int opt)
{
    int mm;
    int first;
    int cc;
	int64_t nn;
 
     //printf("Line: %d\r", lineno);
     segprefix = -1;
     if (bGen && (segment==codeseg || segment==dataseg || segment==rodataseg)) {
    nn = binstart;
    cc = 8;
    if (segment==codeseg) {
       cc = 12;
/*
        if (sections[segment].bytes[binstart]==0x61) {
            fprintf(ofp, "%06LLX ", ca);
            for (nn = binstart; nn < binstart + 5 && nn < sections[segment].index; nn++) {
                fprintf(ofp, "%02X ", sections[segment].bytes[nn]);
            }
            fprintf(ofp, "   ; imm\n");
             if (((ca+5) & 15)==15) {
                 ca+=6;
                 binstart+=6;
                 nn++;
             }
             else {
                  ca += 5;
                  binstart += 5;
             }
        }
*/
/*
        if (sections[segment].bytes[binstart]==0xfd) {
            fprintf(ofp, "%06LLX ", ca);
            for (nn = binstart; nn < binstart + 5 && nn < sections[segment].index; nn++) {
                fprintf(ofp, "%02X ", sections[segment].bytes[nn]);
            }
            fprintf(ofp, "   ; imm\n");
             if (((ca+5) & 15)==15) {
                 ca+=6;
                 binstart+=6;
                 nn++;
             }
             else {
                  ca += 5;
                  binstart += 5;
             }
        }
         if (sections[segment].bytes[binstart]==0xfe) {
            fprintf(ofp, "%06LLX ", ca);
            for (nn = binstart; nn < binstart + 5 && nn < sections[segment].index; nn++) {
                fprintf(ofp, "%02X ", sections[segment].bytes[nn]);
            }
            fprintf(ofp, "   ; imm\n");
             if (((ca+5) & 15)==15) {
                 ca+=6;
                 nn++;
             }
             else {
                  ca += 5;
             }
        }
*/
    }
 
    first = 1;
    while (nn < sections[segment].index) {
        fprintf(ofp, "%06LLX ", ca);
        for (mm = nn; nn < mm + cc && nn < sections[segment].index; nn++) {
            fprintf(ofp, "%02X ", sections[segment].bytes[nn]);
        }
        for (; nn < mm + cc; nn++)
            fprintf(ofp, "   ");
        if (first & opt) {
            fprintf(ofp, "\t%.*s\n", inptr-stptr-1, stptr);
            first = 0;
        }
        else
            fprintf(ofp, opt ? "\n" : "; NOP Ramp\n");
        ca += cc;
    }
    // empty (codeless) line
    if (binstart==sections[segment].index) {
        fprintf(ofp, "%41s\t%.*s", "", inptr-stptr, stptr);
    }
    } // bGen
    if (opt) {
       stptr = inptr;
       lineno++;
    }
//    printf("line:%d\r",lineno);
    binstart = sections[segment].index;
    ca = sections[segment].address;
}
 
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
 
void FISA64_processMaster()
{
    int nn;
    int64_t bs1, bs2;
 
    lineno = 1;
    binndx = 0;
    binstart = 0;
    bs1 = 0;
    bs2 = 0;
    inptr = &masterFile[0];
    stptr = inptr;
    code_address = 0;
    bss_address = 0;
    start_address = 0;
    data_address = 0;
    first_org = 1;
    first_rodata = 1;
    first_data = 1;
    first_bss = 1;
    for (nn = 0; nn < 12; nn++) {
        sections[nn].index = 0;
        if (nn == 0)
        sections[nn].address = 0;
        else
        sections[nn].address = 0;
        sections[nn].start = 0;
        sections[nn].end = 0;
    }
    ca = code_address;
    segment = codeseg;
    memset(current_label,0,sizeof(current_label));
    NextToken();
    while (token != tk_eof) {
//        printf("\t%.*s\n", inptr-stptr-1, stptr);
//        printf("token=%d\r", token);
j_processToken:
        switch(token) {
        case tk_eol: ProcessEOL(1); break;
        case tk_add:  process_rrop(0x04); break;
        case tk_addi: process_riop(0x04); break;
        case tk_addu:  process_rrop(0x14); break;
        case tk_addui: process_riop(0x14); break;
        case tk_align: process_align(); continue; break;
        case tk_and:  process_rrop(12); break;
        case tk_andi:  process_riop(12); break;
        case tk_asl:  process_rrop(0x30); break;
        case tk_asli: process_shifti(0x38); break;
        case tk_asr:  process_rrop(0x34); break;
        case tk_asri: process_shifti(0x3C); break;
        case tk_beq: process_bcc(0); break;
        case tk_bfextu: process_bitfield(6); break;
        case tk_bge: process_bcc(3); break;
        case tk_bgt: process_bcc(2); break;
        case tk_ble: process_bcc(5); break;
        case tk_blt: process_bcc(4); break;
        case tk_bmi: process_bcc(4); break;
        case tk_bne: process_bcc(1); break;
        case tk_bpl: process_bcc(3); break;
        case tk_bra: process_bra(0x3A); break;
        case tk_bsr: process_bra(0x39); break;
//        case tk_bsr: process_bra(0x56); break;
        case tk_bss:
            if (first_bss) {
                while(sections[segment].address & 4095)
                    emitByte(0x00);
                sections[3].address = sections[segment].address;
                first_bss = 0;
                binstart = sections[3].index;
                ca = sections[3].address;
            }
            segment = bssseg;
            break;
        case tk_byte:  process_db(); break;
        case tk_cas: process_load(0x6C); break;
        case tk_chk: process_chk(0x1A); break;
        case tk_cli: process_pctrl(0); break;
        case tk_cmp: process_rrop(0x06); break;
        case tk_cmpu: process_rrop(0x16); break;
        case tk_code: process_code(); break;
        case tk_com: process_com(); break;
        case tk_cpuid: process_cpuid(0x36); break;
        case tk_data:
             // Process data declarations as if we are in the rodata segment
             // for initialization data.
             if (isInitializationData) {
                 token = tk_rodata;
                 goto j_processToken;
             }
            if (first_data) {
                while(sections[segment].address & 4095)
                    emitByte(0x00);
                sections[2].address = sections[segment].address;   // set starting address
                first_data = 0;
                binstart = sections[2].index;
                ca = sections[2].address;
            }
            process_data(dataseg);
            break;
        case tk_db:  process_db(); break;
        case tk_dc:  process_dc(); break;
        case tk_dec: process_inc(0x65); break;
        case tk_dh:  process_dh(); break;
        case tk_div: process_rrop(0x08); break;
        case tk_divu: process_rrop(0x18); break;
        case tk_dw:  process_dw(); break;
        case tk_end: goto j1;
        case tk_endpublic: break;
        case tk_eor: process_rrop(0x0E); break;
        case tk_eori: process_riop(0x0E); break;
        case tk_extern: process_extern(); break;
 
        case tk_fabs: process_fprop(0x64); break;
        case tk_fadd: process_fprrop(0x28); break;
        case tk_fcmp: process_fprrop(0x2A); break;
        case tk_fdiv: process_fprrop(0x2C); break;
        case tk_mffp: process_fprop(0x65); break;
        case tk_mv2fix: process_fprop(0x66); break;
        case tk_mv2flt: process_fprop(0x1D); break;
        case tk_mtfp: process_fprop(0x1C); break;
/*
        case tk_fcx: process_fpstat(0x74); break;
        case tk_fdx: process_fpstat(0x77); break;
        case tk_fex: process_fpstat(0x76); break;
*/
        case tk_fill: process_fill(); break;
        case tk_fix2flt: process_fprop(0x60); break;
        case tk_flt2fix: process_fprop(0x61); break;
        case tk_fmov: process_fprop(0x62); break;
        case tk_fmul: process_fprrop(0x2B); break;
/*
        case tk_fnabs: process_fprop(0x89); break;
        case tk_frm: process_fpstat(0x78); break;
        case tk_fstat: process_fprdstat(0x86); break;
        case tk_ftx: process_fpstat(0x75); break;
*/
        case tk_fneg: process_fprop(0x63); break;
        case tk_fsub: process_fprrop(0x29); break;
 
        case tk_gran: process_gran(0x14); break;
        case tk_inc: process_inc(0x64); break;
        case tk_int: process_brk(2); break;
 
        case tk_jal: process_jal(0x3C,-1); break;
        case tk_jmp: process_jal(0x3C,0); break;
        case tk_jsr: process_jal(0x3C,31); break;
 
        case tk_lb:  process_load(0x40); break;
        case tk_lbu: process_load(0x41); break;
        case tk_lc:  process_load(0x42); break;
        case tk_lcu: process_load(0x43); break;
        case tk_ldi: process_ldi(0x0A); break;
        case tk_lea: process_load(0x47); break;
        case tk_lfd: process_load(0x51); break;
        case tk_lh:  process_load(0x44); break;
        case tk_lhu: process_load(0x45); break;
        case tk_lsr: process_rrop(0x31); break;
        case tk_lsri: process_shifti(0x39); break;
        case tk_lw:  process_load(0x46); break;
        case tk_lwar:  process_load(0x5C); break;
        case tk_message: process_message(); break;
        case tk_mfspr: process_mfspr(0x1F); break;
        case tk_mod: process_rrop(0x09); break;
        case tk_modu: process_rrop(0x19); break;
        case tk_mov: process_mov(); break;
        case tk_mtspr: process_mtspr(0x1E); break;
        case tk_mul: process_rrop(0x07); break;
        case tk_muli: process_riop(0x07); break;
        case tk_mulu: process_rrop(0x17); break;
        case tk_mului: process_riop(0x17); break;
        case tk_neg: process_neg(0x15); break;
        case tk_nop: emit_insn(0x0000003F); break;
        case tk_not: process_rop(0x0A); break;
        case tk_or:  process_rrop(0x0D); break;
        case tk_ori: process_riop(0x0D); break;
        case tk_org: process_org(); break;
        case tk_pea: process_pea(); break;
        case tk_pop:  process_pushpop(0x57); break;
        case tk_public: process_public(); break;
        case tk_push: process_pushpop(0x67); break;
        case tk_rodata:
            if (first_rodata) {
                while(sections[segment].address & 4095)
                    emitByte(0x00);
                sections[1].address = sections[segment].address;
                first_rodata = 0;
                binstart = sections[1].index;
                ca = sections[1].address;
            }
            segment = rodataseg;
            break;
        case tk_rol: process_rrop(0x32); break;
        case tk_ror: process_rrop(0x33); break;
        case tk_roli: process_shifti(0x3A); break;
        case tk_rori: process_shifti(0x3B); break;
        case tk_rtd: process_pctrl(29); break;
        case tk_rte: process_pctrl(30); break;
        case tk_rti: process_pctrl(31); break;
        case tk_rtl: process_rts(0x27); break;
        case tk_rts: process_rts(0x3B); break;
        case tk_sb:  process_store(0x60); break;
        case tk_sc:  process_store(0x61); break;
        case tk_sei: process_pctrl(1); break;
        case tk_seq:  process_rrop(0x20); break;
        case tk_sfd: process_store(0x71); break;
        case tk_sh:  process_store(0x62); break;
        case tk_shl:  process_rrop(0x30); break;
        case tk_shli: process_shifti(0x38); break;
        case tk_sne:  process_rrop(0x21); break;
        case tk_stp: process_pctrl(2); break;
        case tk_sub:  process_rrop(0x05); break;
        case tk_subi: process_riop(0x05); break;
        case tk_subu:  process_rrop(0x15); break;
        case tk_subui: process_riop(0x15); break;
        case tk_sxb: process_rop(0x10); break;
        case tk_sxc: process_rop(0x11); break;
        case tk_sxh: process_rop(0x12); break;
        case tk_sys: process_brk(0); break;
        case tk_sw:  process_store(0x63); break;
        case tk_swcr:  process_store(0x6E); break;
        case tk_xor: process_rrop(0x0E); break;
        case tk_xori: process_riop(0x0E); break;
        case tk_wai: process_pctrl(3); break;
        case tk_id:  process_label(); break;
        }
        NextToken();
    }
j1:
    ;
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.