Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / bin / SS_InstrCti.py
# ========== Copyright Header Begin ==========================================
#
# OpenSPARC T2 Processor File: SS_InstrCti.py
# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
#
# The above named program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License version 2 as published by the Free Software Foundation.
#
# The above named program 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 work; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ========== Copyright Header End ============================================
#============================================================================
# SS_Cti.py
#
# All Control Transfer Instruction (CTI) decode and implementation
#============================================================================
from SS_Instr import *
from SS_Setup import *
setup = setups[sys.argv[1]]
#============================================================================
# The not-annulled versions (_a0) of the branches do
#
# n : pc = npc , npc = npc+4
# a : pc = npc , npc = ea
# c : pc = npc , npc = c ? ea : npc+4
#
# annulled versions (_a1) of the branches do
#
# n : pc = npc+4 , npc = npc+8
# a : pc = ea , npc = ea+4
# c : pc = c ? npc : npc+4 , npc = c ? ea : npc+8
#============================================================================
#============================================================================
# SS_bp_a0(cc,ccr)
#============================================================================
class SS_bp_a0(SS_InstrAsm):
def __init__(self,cc,ccr):
SS_InstrAsm.__init__(self,'bp'+cc+'_'+ccr+'_a0')
self.cc = cc
self.ccr = ccr
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
if (self.cc == 'n'):
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,4,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.mov(file,self.NPC,self.PC)
self.ld_ea_rd(file,self.NPC)
self.retl_st_npc(file,self.NPC)
else:
self.mov(file,self.NPC,self.PC)
self.ld_ccr(file,'%g1')
self.add(file,self.NPC,4,self.NPC)
self.ld_ea_rd(file,'%g2')
self.wr_ccr(file,'%g1')
self.movcc(file,self.cc,'%'+self.ccr,'%g2',self.NPC)
self.retl_st_npc(file,self.NPC)
self.asm_codesize(file,'run_exe_'+self.name)
self.asm_function(file,'run_tct_'+self.name)
if (self.cc == 'n'):
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,'4',self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_trap(file,'%g5')
self.jmpl(file,'%g5','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
else:
self.ld_ccr(file,'%g1')
self.ld_trap(file,'%g5')
self.add(file,self.NPC,4,'%g4')
self.wr_ccr(file,'%g1')
self.branch(file,self.cc,'%'+self.ccr,'1f')
self.nop(file)
self.mov(file,self.NPC,self.PC)
self.retl(file)
self.st_npc(file,'%g4')
file.write('1:\n')
self.jmpl(file,'%g5','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
self.asm_codesize(file,'run_tct_'+self.name)
def gen_exe_tbl(self,file,mode):
if mode == 'trc':
file.write(' trc_exe_passthrough, /* exe_'+self.name+' */\n')
file.write(' trc_exe_passthrough, /* tct_'+self.name+' */\n')
elif mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
file.write(' run_exe_v8plus_to_v9, /* run_tct_'+self.name+' */\n')
else:
file.write(' %s_exe_%s,\n' % (mode,self.name))
file.write(' %s_tct_%s,\n' % (mode,self.name))
def idx_exe_s(self,file):
self.idx_exe_s_name(file,'exe_'+self.name)
self.idx_exe_s_name(file,'tct_'+self.name)
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
file.write(' pc = npc;\n')
self.test_icc(file,' ')
file.write(' s->npc = (SS_Vaddr&)i->rd;\n')
file.write(' else\n')
file.write(' s->npc = npc+4;\n')
file.write(' return pc;\n')
self.c_code_end(file)
self.c_code_beg(file,'run_tct_')
self.test_icc(file,' ')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' else {\n')
file.write(' pc = npc;\n')
file.write(' s->npc = npc+4;\n')
file.write(' return pc;\n')
file.write(' }\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('extern "C" SS_Vaddr run_tct_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('#endif\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_%s;\n' % self.name)
file.write(' else\n')
file.write(' idx = idx_exe_%s;\n' % self.name)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp19();\n')
self.c_code_dec_end(file)
#============================================================================
# bp_a1
#============================================================================
class SS_bp_a1(SS_InstrAsm):
def __init__(self,cc,ccr):
SS_InstrAsm.__init__(self,'bp'+cc+'_'+ccr+'_a1')
self.cc = cc
self.ccr = ccr
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
if (self.cc == 'n'):
self.add(file,self.NPC,4,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_ea_rd(file,self.PC)
self.add(file,self.PC,4,self.NPC)
self.retl_st_npc(file,self.NPC)
else:
self.ld_ccr(file,'%g1')
self.add(file,self.NPC,4,self.PC)
self.ld_ea_rd(file,'%g2')
self.wr_ccr(file,'%g1')
self.movcc(file,self.cc,'%'+self.ccr,self.NPC,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.movcc(file,self.cc,'%'+self.ccr,'%g2',self.NPC)
self.retl_st_npc(file,self.NPC)
self.asm_codesize(file,'run_exe_'+self.name)
self.asm_function(file,'run_tct_'+self.name)
if (self.cc == 'n'):
self.add(file,self.NPC,4,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_trap(file,'%g5')
self.jmpl(file,'%g5','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
else:
self.ld_ccr(file,'%g1')
self.ld_trap(file,'%g5')
self.add(file,self.NPC,8,'%g4')
self.wr_ccr(file,'%g1')
self.branch(file,self.cc,'%'+self.ccr,'1f')
self.nop(file)
self.add(file,self.NPC,4,self.PC)
self.retl(file)
self.st_npc(file,'%g4')
file.write('1:\n')
self.jmpl(file,'%g5','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
self.asm_codesize(file,'run_tct_'+self.name)
def gen_exe_tbl(self,file,mode):
if mode == 'trc':
file.write(' trc_exe_passthrough, /* exe_'+self.name+' */\n')
file.write(' trc_exe_passthrough, /* tct_'+self.name+' */\n')
elif mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
file.write(' run_exe_v8plus_to_v9, /* run_tct_'+self.name+' */\n')
else:
file.write(' %s_exe_%s,\n' % (mode,self.name))
file.write(' %s_tct_%s,\n' % (mode,self.name))
def idx_exe_s(self,file):
self.idx_exe_s_name(file,'exe_'+self.name)
self.idx_exe_s_name(file,'tct_'+self.name)
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
if (self.cc == 'a'):
file.write(' SS_Vaddr target = (SS_Vaddr&)i->rd;\n')
file.write(' pc = target;\n')
file.write(' s->npc = target+4;\n')
else:
self.test_icc(file,' ')
file.write(' {\n')
file.write(' pc = npc;\n')
file.write(' s->npc = (SS_Vaddr&)i->rd;\n')
file.write(' }\n')
file.write(' else {\n')
file.write(' pc = npc + 4;\n')
file.write(' s->npc = npc + 8;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
self.c_code_beg(file,'run_tct_')
self.test_icc(file,' ')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' else {\n')
file.write(' pc = npc + 4;\n')
file.write(' s->npc = npc + 8;\n')
file.write(' return pc;\n')
file.write(' }\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('extern "C" SS_Vaddr run_tct_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('#endif\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_%s;\n' % self.name)
file.write(' else\n')
file.write(' idx = idx_exe_%s;\n' % self.name)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp19();\n')
self.c_code_dec_end(file)
#============================================================================
# bi_a0
#============================================================================
class SS_bi_a0(SS_InstrAsm):
def __init__(self,cc):
SS_InstrAsm.__init__(self,'bi'+cc+'_a0')
self.cc = cc
def idx_exe_s(self,file):
pass
def gen_exe_tbl(self,file,mode):
pass
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_bp%s_icc_a0;\n' % self.cc)
file.write(' else\n')
file.write(' idx = idx_exe_bp%s_icc_a0;\n' % self.cc)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp22();\n')
self.c_code_dec_end(file)
#============================================================================
# bi_a1
#============================================================================
class SS_bi_a1(SS_InstrAsm):
def __init__(self,cc):
SS_InstrAsm.__init__(self,'bi'+cc+'_a1')
self.cc = cc
def idx_exe_s(self,file):
pass
def gen_exe_tbl(self,file,mode):
pass
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_bp%s_icc_a1;\n' % self.cc)
file.write(' else\n')
file.write(' idx = idx_exe_bp%s_icc_a1;\n' % self.cc)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp22();\n')
self.c_code_dec_end(file)
#============================================================================
# br_a0
#============================================================================
class SS_br_a0(SS_InstrAsm):
def __init__(self,cc):
SS_InstrAsm.__init__(self,'br'+cc+'_a0')
self.cc = cc
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
self.mov(file,self.PC,'%g3')
self.mov(file,self.NPC,self.PC)
self.ld_rs1(file,'%g1')
self.ld_imm(file,'%g2')
self.add(file,self.PC,4,self.NPC)
self.ld_irf(file,'%g1','%g1')
self.opr(file,'sllx','%g2','2','%g2')
self.add(file,'%g2','%g3','%g2')
self.movr(file,self.cc,'%g1','%g2',self.NPC)
self.retl_st_npc(file,self.NPC)
self.asm_codesize(file,'run_exe_'+self.name)
self.asm_function(file,'run_tct_'+self.name)
self.ld_rs1(file,'%g1')
self.ld_trap(file,'%g5')
self.ld_irf(file,'%g1','%g1')
self.add(file,self.NPC,4,'%g4')
self.branch(file,'r'+self.cc,'%g1','1f')
self.nop(file)
self.mov(file,self.NPC,self.PC)
self.retl(file)
self.st_npc(file,'%g4')
file.write('1:\n')
self.jmpl(file,'%g5','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
self.asm_codesize(file,'run_tct_'+self.name)
def gen_exe_tbl(self,file,mode):
if mode == 'trc':
file.write(' trc_exe_passthrough, /* exe_'+self.name+' */\n')
file.write(' trc_exe_passthrough, /* tct_'+self.name+' */\n')
elif mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
file.write(' run_exe_v8plus_to_v9, /* run_tct_'+self.name+' */\n')
else:
file.write(' %s_exe_%s,\n' % (mode,self.name))
file.write(' %s_tct_%s,\n' % (mode,self.name))
def idx_exe_s(self,file):
self.idx_exe_s_name(file,'exe_'+self.name)
self.idx_exe_s_name(file,'tct_'+self.name)
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
self.test_r(file,' ')
file.write(' {\n')
file.write(' int off = i->rs2;\n')
file.write(' off <<= 2;\n')
file.write(' uint64_t ea = pc + off;\n')
file.write(' pc = npc;\n')
file.write(' s->npc = ea;\n')
file.write(' }\n')
file.write(' else {\n')
file.write(' pc = npc;\n')
file.write(' s->npc = npc + 4;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
self.c_code_beg(file,'run_tct_')
self.test_r(file,' ')
file.write(' {\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' }\n')
file.write(' else {\n')
file.write(' pc = npc;\n')
file.write(' s->npc = npc + 4;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('extern "C" SS_Vaddr run_tct_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('#endif\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
self.dec_0r16(file,' ','idx_tct_'+self.name)
file.write(' else\n')
self.dec_0r16(file,' ','idx_exe_'+self.name)
self.c_code_end(file)
#============================================================================
# br_a1
#============================================================================
class SS_br_a1(SS_InstrAsm):
def __init__(self,cc):
SS_InstrAsm.__init__(self,'br'+cc+'_a1')
self.cc = cc
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
self.mov(file,self.PC,'%g3')
self.add(file,self.NPC,4,self.PC)
self.ld_rs1(file,'%g1')
self.ld_imm(file,'%g2')
self.ld_irf(file,'%g1','%g1')
self.movr(file,self.cc,'%g1',self.NPC,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.opr(file,'sllx','%g2','2','%g2')
self.add(file,'%g2','%g3','%g2')
self.movr(file,self.cc,'%g1','%g2',self.NPC)
self.retl_st_npc(file,self.NPC)
self.asm_codesize(file,'run_exe_'+self.name)
self.asm_function(file,'run_tct_'+self.name)
self.ld_rs1(file,'%g1')
self.ld_trap(file,'%g5')
self.ld_irf(file,'%g1','%g1')
self.add(file,self.NPC,8,'%g4')
self.branch(file,'r'+self.cc,'%g1','1f')
self.nop(file)
self.add(file,self.NPC,4,self.PC)
self.retl(file)
self.st_npc(file,'%g4')
file.write('1:\n')
self.jmpl(file,'%g5','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
self.asm_codesize(file,'run_tct_'+self.name)
def gen_exe_tbl(self,file,mode):
if mode == 'trc':
file.write(' trc_exe_passthrough, /* exe_'+self.name+' */\n')
file.write(' trc_exe_passthrough, /* tct_'+self.name+' */\n')
elif mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
file.write(' run_exe_v8plus_to_v9, /* run_tct_'+self.name+' */\n')
else:
file.write(' %s_exe_%s,\n' % (mode,self.name))
file.write(' %s_tct_%s,\n' % (mode,self.name))
def idx_exe_s(self,file):
self.idx_exe_s_name(file,'exe_'+self.name)
self.idx_exe_s_name(file,'tct_'+self.name)
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
self.test_r(file,' ')
file.write(' {\n')
file.write(' int off = i->rs2;\n')
file.write(' off <<= 2;\n')
file.write(' uint64_t ea = pc + off;\n')
file.write(' pc = npc;\n')
file.write(' s->npc = ea;\n')
file.write(' }\n')
file.write(' else {\n')
file.write(' pc = npc + 4;\n')
file.write(' s->npc = npc + 8;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
self.c_code_beg(file,'run_tct_')
self.test_r(file,' ')
file.write(' {\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' }\n')
file.write(' else {\n')
file.write(' pc = npc + 4;\n')
file.write(' s->npc = npc + 8;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('extern "C" SS_Vaddr run_tct_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('#endif\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
self.dec_0r16(file,' ','idx_tct_'+self.name)
file.write(' else\n')
self.dec_0r16(file,' ','idx_exe_'+self.name)
self.c_code_end(file)
#============================================================================
# fbp_a0
#============================================================================
class SS_fbp_a0(SS_InstrAsm):
def __init__(self,cc,ccr):
SS_InstrAsm.__init__(self,'fbp'+cc+'_'+ccr+'_a0')
self.cc = cc
self.ccr = ccr
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
if (self.cc == 'n'):
self.ld_sim(file,'%g5')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,4,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_sim(file,'%g5')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.mov(file,self.NPC,self.PC)
self.ld_ea_rd(file,self.NPC)
self.retl_st_npc(file,self.NPC)
else:
self.ld_sim(file,'%g5')
self.st_fsr_cpu(file,'%fsr')
self.ld_ea_rd(file,'%g2')
self.ld_fsr_run(file,'%fsr')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap_fsr')
self.nop(file)
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,4,self.NPC)
self.movcc(file,self.cc,'%'+self.ccr,'%g2',self.NPC)
self.ld_fsr_cpu(file,'%fsr')
self.retl_st_npc(file,self.NPC)
self.asm_codesize(file,'run_exe_'+self.name)
self.asm_function(file,'run_tct_'+self.name)
if (self.cc == 'n'):
self.ld_sim(file,'%g5')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,4,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_sim(file,'%g5')
self.ld_trap(file,'%g4')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.jmpl(file,'%g4','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
else:
self.ld_sim(file,'%g5')
self.st_fsr_cpu(file,'%fsr')
self.ld_trap(file,'%g4')
self.ld_fsr_run(file,'%fsr')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap_fsr')
self.nop(file)
self.branch(file,self.cc,'%'+self.ccr,'1f')
self.nop(file)
self.ld_fsr_cpu(file,'%fsr')
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,4,self.NPC)
self.retl_st_npc(file,self.NPC)
file.write('1:\n')
self.jmpl(file,'%g4','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
self.asm_codesize(file,'run_tct_'+self.name)
def gen_exe_tbl(self,file,mode):
if mode == 'trc':
file.write(' trc_exe_passthrough, /* exe_'+self.name+' */\n')
file.write(' trc_exe_passthrough, /* tct_'+self.name+' */\n')
elif mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
file.write(' run_exe_v8plus_to_v9, /* run_tct_'+self.name+' */\n')
else:
file.write(' %s_exe_%s,\n' % (mode,self.name))
file.write(' %s_tct_%s,\n' % (mode,self.name))
def idx_exe_s(self,file):
self.idx_exe_s_name(file,'exe_'+self.name)
self.idx_exe_s_name(file,'tct_'+self.name)
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
file.write(' if (s->sim_state.fp_disabled())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);\n')
file.write(' pc = npc;\n')
self.test_fcc(file,' ')
file.write(' s->npc = (SS_Vaddr&)i->rd;\n')
file.write(' else\n')
file.write(' s->npc = npc + 4;\n')
file.write(' return pc;\n')
self.c_code_end(file)
self.c_code_beg(file,'run_tct_')
file.write(' if (s->sim_state.fp_disabled())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);\n')
self.test_fcc(file,' ')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' else {\n')
file.write(' pc = npc;\n')
file.write(' s->npc = npc + 4;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('extern "C" SS_Vaddr run_tct_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('#endif\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_%s;\n' % self.name)
file.write(' else\n')
file.write(' idx = idx_exe_%s;\n' % self.name)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp19();\n')
self.c_code_dec_end(file)
#============================================================================
# fbp_a1
#============================================================================
class SS_fbp_a1(SS_InstrAsm):
def __init__(self,cc,ccr):
SS_InstrAsm.__init__(self,'fbp'+cc+'_'+ccr+'_a1')
self.cc = cc
self.ccr = ccr
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
if (self.cc == 'n'):
self.ld_sim(file,'%g5')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.add(file,self.NPC,4,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_sim(file,'%g5')
self.ld_ea_rd(file,'%g2')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.mov(file,'%g2',self.PC)
self.add(file,'%g2',4,self.NPC)
self.retl_st_npc(file,self.NPC)
else:
self.ld_sim(file,'%g5')
self.st_fsr_cpu(file,'%fsr')
self.ld_ea_rd(file,'%g2')
self.ld_fsr_run(file,'%fsr')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap_fsr')
self.nop(file)
self.add(file,self.NPC,4,self.PC)
self.movcc(file,self.cc,'%'+self.ccr,self.NPC,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.movcc(file,self.cc,'%'+self.ccr,'%g2',self.NPC)
self.ld_fsr_cpu(file,'%fsr')
self.retl_st_npc(file,self.NPC)
self.asm_codesize(file,'run_exe_'+self.name)
self.asm_function(file,'run_tct_'+self.name)
if (self.cc == 'n'):
self.ld_sim(file,'%g5')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.add(file,self.NPC,4,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_sim(file,'%g5')
self.ld_trap(file,'%g4')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap')
self.nop(file)
self.jmpl(file,'%g4','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
else:
self.ld_sim(file,'%g5')
self.st_fsr_cpu(file,'%fsr')
self.ld_trap(file,'%g4')
self.ld_fsr_run(file,'%fsr')
self.andcc(file,'%g5','F_FP_DISABLED','%g0')
self.branch(file,'ne,a','%xcc','fpop_disabled_trap_fsr')
self.nop(file)
self.branch(file,self.cc,'%'+self.ccr,'1f')
self.nop(file)
self.ld_fsr_cpu(file,'%fsr')
self.add(file,self.NPC,4,self.PC)
self.add(file,self.NPC,8,self.NPC)
self.retl_st_npc(file,self.NPC)
file.write('1:\n')
self.jmpl(file,'%g4','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
self.asm_codesize(file,'run_tct_'+self.name)
def gen_exe_tbl(self,file,mode):
if mode == 'trc':
file.write(' trc_exe_passthrough, /* exe_'+self.name+' */\n')
file.write(' trc_exe_passthrough, /* tct_'+self.name+' */\n')
elif mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
file.write(' run_exe_v8plus_to_v9, /* run_tct_'+self.name+' */\n')
else:
file.write(' %s_exe_%s,\n' % (mode,self.name))
file.write(' %s_tct_%s,\n' % (mode,self.name))
def idx_exe_s(self,file):
self.idx_exe_s_name(file,'exe_'+self.name)
self.idx_exe_s_name(file,'tct_'+self.name)
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
file.write(' if (s->sim_state.fp_disabled())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);\n')
if (self.cc == 'a'):
file.write(' SS_Vaddr target = (SS_Vaddr&)i->rd;\n')
file.write(' pc = target;\n')
file.write(' s->npc = target + 4;\n')
else:
self.test_fcc(file,' ')
file.write(' {\n')
file.write(' pc = npc;\n')
file.write(' s->npc = (SS_Vaddr&)i->rd;\n')
file.write(' }\n')
file.write(' else {\n')
file.write(' pc = npc + 4;\n')
file.write(' s->npc = npc + 8;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
self.c_code_beg(file,'run_tct_')
file.write(' if (s->sim_state.fp_disabled())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);\n')
self.test_fcc(file,' ')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' else {\n')
file.write(' pc = npc + 4;\n')
file.write(' s->npc = npc + 8;\n')
file.write(' }\n')
file.write(' return pc;\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('extern "C" SS_Vaddr run_tct_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % self.name)
file.write('#endif\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_%s;\n' % self.name)
file.write(' else\n')
file.write(' idx = idx_exe_%s;\n' % self.name)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp19();\n')
self.c_code_dec_end(file)
#============================================================================
# fbi_a0
#============================================================================
class SS_fbi_a0(SS_InstrAsm):
def __init__(self,cc):
SS_InstrAsm.__init__(self,'fbi'+cc+'_a0')
self.cc = cc
def idx_exe_s(self,file):
pass
def gen_exe_tbl(self,file,mode):
pass
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_fbp%s_fcc0_a0;\n' % self.cc)
file.write(' else\n')
file.write(' idx = idx_exe_fbp%s_fcc0_a0;\n' % self.cc)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp22();\n')
self.c_code_dec_end(file)
#============================================================================
# fbi_a1
#============================================================================
class SS_fbi_a1(SS_InstrAsm):
def __init__(self,cc):
SS_InstrAsm.__init__(self,'fbi'+cc+'_a1')
self.cc = cc
def idx_exe_s(self,file):
pass
def gen_exe_tbl(self,file,mode):
pass
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_fbp%s_fcc0_a1;\n' % self.cc)
file.write(' else\n')
file.write(' idx = idx_exe_fbp%s_fcc0_a1;\n' % self.cc)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp22();\n')
self.c_code_dec_end(file)
#============================================================================
# SS_call()
#============================================================================
class SS_call(SS_InstrAsm):
def __init__(self):
SS_InstrAsm.__init__(self,'call')
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
self.ld_mask_pstate_am(file,'%g5')
self.mov(file,self.PC,'%g4')
self.mov(file,self.NPC,self.PC)
self.ld_ea_rd(file,self.NPC)
self.opr(file,'and','%g4','%g5','%g5')
# ToDo do we need to sign extend the pc ... ironically that case should be a mem range trap
if setup.va_bits != 64:
self.opr(file,'sllx','%g5',str(64 - setup.va_bits),'%g5')
self.opr(file,'srax','%g5',str(64 - setup.va_bits),'%g5')
self.st_npc(file,self.NPC)
self.retl(file)
self.st_o7(file,'%g5')
self.asm_codesize(file,'run_exe_'+self.name)
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
file.write(' pc &= s->mask_pstate_am;\n')
if setup.va_bits != 64:
file.write(' pc = ((((int64_t)pc) << '+str(64-setup.va_bits)+') >> '+str(64-setup.va_bits)+');\n')
file.write(' s->irf[15] = pc;\n')
file.write(' s->npc = (SS_Vaddr&)i->rd;\n')
file.write(' return npc;\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % (self.name))
file.write('#endif\n\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
file.write(' idx = idx_tct_bpa_icc_a0;\n')
file.write(' else\n')
file.write(' idx = idx_exe_%s;\n' % self.name)
file.write(' i->exe_tbl_idx = idx;\n')
file.write(' i->exe = s->exe_table[idx];\n')
file.write(' (SS_Vaddr&)i->rd = pc + o.get_disp30();\n')
self.c_code_dec_end(file)
def run_dec_p_count(self):
return 64
def gen_exe_tbl(self,file,mode):
if mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
else:
file.write(' %s_exe_%s,\n' % (mode,self.name))
#============================================================================
# SS_illtrap()
#=================================t===========================================
class SS_illtrap(SS_InstrCpp):
def __init__(self):
SS_InstrCpp.__init__(self,'illtrap')
def run_exe_c(self,file):
self.c_code_beg(file,'run_exe_')
file.write(' assert(0);\n')
file.write(' return -SS_Vaddr(1);\n')
self.c_code_end(file)
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self.c_code_dec_end(file)
def run_dec_p_count(self):
return 8
def gen_exe_tbl(self,file,mode):
self.gen_exe_passthrough(file,mode)
#============================================================================
# SS_jmpl(imm,out)
#
# ToDo: optimize common patters (retl) jmpl %o7+8,%g0, (call) jmpl %r,%o7
# and (tailcall) jmpl %r,%g0
#============================================================================
class SS_jmpl(SS_InstrAsm):
def __init__(self):
SS_InstrAsm.__init__(self,'jmpl')
self.opc = 'jmpl'
self.imm = ['i0' ,'i1']
self.out = ['rd' ,'g0']
def run_exe_c(self,file):
for out in self.out:
for imm in self.imm:
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg_name(file,'run_exe_jmpl_'+imm+'_'+out)
file.write(' uint64_t mask = s->mask_pstate_am;\n')
if imm == 'i0':
file.write(' uint64_t rs1 = s->get_irf(i->rs1);\n')
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
else:
file.write(' uint64_t rs1 = s->get_irf(i->rs1);\n')
file.write(' int rs2 = i->rs2;\n');
# First check for aligned address
file.write(' uint64_t target = rs1 + rs2;\n')
file.write(' if (target & 0x3)\n')
file.write(' return (s->inst_trap)(pc,npc,s,i,target,SS_Trap::MEM_ADDRESS_NOT_ALIGNED);\n')
# Then check for address range if va_bits != 64
if setup.va_bits != 64:
file.write(' uint64_t t1 = target & mask;\n')
file.write(' uint64_t t = (((int64_t)t1) << '+str(64 - setup.va_bits)+') >> '+str(64 - setup.va_bits)+';\n')
file.write(' if (t != t1)\n')
file.write(' // Do not generate trap in HPRV or RED mode (IMMU bypass)\n')
file.write(' if (s->sim_state.mode() < 2)\n')
file.write(' return (s->inst_trap)(pc,npc,s,i,target,SS_Trap::MEM_ADDRESS_RANGE);\n')
if out == 'rd':
file.write(' pc &= mask;\n')
if setup.va_bits != 64:
file.write(' pc = (((int64_t)pc) << '+str(64-setup.va_bits)+') >> '+str(64-setup.va_bits)+';\n')
file.write(' s->get_irf(i->rd) = pc;\n')
file.write(' s->npc = target;\n')
file.write(' return npc;\n')
self.c_code_end(file)
file.write('#else\n')
file.write('\nextern "C" SS_Vaddr run_exe_'+self.opc+'_'+imm+'_'+out+'( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i );\n')
file.write('#endif\n')
for imm in self.imm:
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg_name(file,'run_tct_jmpl_'+imm)
file.write(' uint64_t mask = s->mask_pstate_am;\n')
if imm == 'i0':
file.write(' uint64_t rs1 = s->get_irf(i->rs1);\n')
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
else:
file.write(' uint64_t rs1 = s->get_irf(i->rs1);\n')
file.write(' int rs2 = i->rs2;\n');
# First check for aligned address
file.write(' uint64_t target = rs1 + rs2;\n')
file.write(' if (target & 0x3)\n')
file.write(' return (s->inst_trap)(pc,npc,s,i,target,SS_Trap::MEM_ADDRESS_NOT_ALIGNED);\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
self.c_code_end(file)
file.write('#else\n')
file.write('\nextern "C" SS_Vaddr run_tct_'+self.opc+'_'+imm+'( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i );\n')
file.write('#endif\n')
def run_exe_s(self,file):
for out in self.out:
for imm in self.imm:
self.asm_function(file,'run_exe_'+self.opc+'_'+imm+'_'+out)
if imm == 'i0':
self.ld_rs1(file,'%g1')
self.ld_rs2(file,'%g2')
self.ld_mask_pstate_am(file,'%g4')
self.ld_irf(file,'%g1','%g1')
self.ld_irf(file,'%g2','%g2')
else:
self.ld_rs1(file,'%g1')
self.ld_imm(file,'%g2')
self.ld_mask_pstate_am(file,'%g4')
self.ld_irf(file,'%g1','%g1')
if out == 'rd':
self.opr(file,'and',self.PC,'%g4','%g5')
self.ld_rd(file,'%g3')
if setup.va_bits != 64:
self.opr(file,'sllx','%g5',str(64 - setup.va_bits),'%g5')
self.opr(file,'srax','%g5',str(64 - setup.va_bits),'%g5')
# First check for aligned address
# Then check for address range if va_bits != 64
self.add(file,'%g1','%g2','%g1')
self.opr(file,'andcc','%g1',3,'%g0')
if setup.va_bits != 64:
self.opr(file,'and','%g1','%g4','%g4')
self.branch(file,'e','%icc','1f')
self.opr(file,'srax','%g4',str(setup.va_bits - 1),'%g4')
elif out == 'rd':
self.branch(file,'e,a','%icc','1f')
self.st_irf(file,'%g3','%g5')
else:
self.branch(file,'e,a','%icc','1f')
self.nop(file)
self.ld_inst_trap(file,'%g2')
self.mov(file,'%g1','%o4')
self.jmpl(file,'%g2','%g0','%g0')
self.mov(file,'T_MEM_ADDRESS_NOT_ALIGNED','%o5')
if setup.va_bits != 64:
file.write('1:\n')
self.add(file,'%g4','1','%g4')
self.ld_sim(file,'%g2')
self.opr(file,'subcc','%g4','1','%g0')
self.branch(file,'leu','%xcc','2f')
self.nop(file)
# Don't generate the MEM_ADDRESS_RANGE trap in HPRV or RED mode (IMMU bypass)
self.opr(file,'and','%g2','7','%g2') # priv() and red() -> sim_state.mode()
self.opr(file,'subcc','%g2','2','%g0')
self.branch(file,'ge,a','%xcc','2f')
self.nop(file)
self.ld_inst_trap(file,'%g2')
self.mov(file,'%g1','%o4')
self.jmpl(file,'%g2','%g0','%g0')
self.mov(file,'T_MEM_ADDRESS_RANGE','%o5')
file.write('2:\n')
else:
file.write('1:\n')
self.mov(file,self.NPC,self.PC)
if out == 'rd' and setup.va_bits != 64:
self.st_irf(file,'%g3','%g5')
self.mov(file,'%g1',self.NPC)
self.retl_st_npc(file,self.NPC)
self.asm_codesize(file,'run_exe_'+self.opc+'_'+imm+'_'+out)
for imm in self.imm:
self.asm_function(file,'run_tct_'+self.opc+'_'+imm)
if imm == 'i0':
self.ld_rs1(file,'%g1')
self.ld_rs2(file,'%g2')
self.ld_irf(file,'%g1','%g1')
self.ld_irf(file,'%g2','%g2')
else:
self.ld_rs1(file,'%g1')
self.ld_imm(file,'%g2')
self.ld_irf(file,'%g1','%g1')
self.add(file,'%g1','%g2','%g1')
self.opr(file,'andcc','%g1',3,'%g0')
self.branch(file,'e,a','%icc','1f')
self.ld_trap(file,'%g4')
self.ld_inst_trap(file,'%g2')
self.mov(file,'%g1','%o4')
self.jmpl(file,'%g2','%g0','%g0')
self.mov(file,'T_MEM_ADDRESS_NOT_ALIGNED','%o5')
file.write('1:\n')
self.jmpl(file,'%g4','%g0','%g0')
self.mov(file,'T_CONTROL_TRANSFER_INSTRUCTION','%o4')
self.asm_codesize(file,'run_tct_'+self.opc+'_'+imm)
def run_dec_c(self,file):
self.c_code_dec_beg_name(file,'run_dec_jmpl')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
file.write(' if (o.get_i())\n')
file.write(' {\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
self.dec_0r13(file,' ','idx_tct_jmpl_i1')
file.write(' else\n')
file.write(' {\n')
file.write(' if (o.get_rd_irf())\n')
self.dec_rr13(file,' ','idx_exe_jmpl_i1_rd')
file.write(' else\n')
self.dec_0r13(file,' ','idx_exe_jmpl_i1_g0')
file.write(' }\n')
file.write(' }\n')
file.write(' else if (o.is_zero_12_5())\n')
file.write(' {\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
self.dec_0rr(file,' ','idx_tct_jmpl_i0')
file.write(' else\n')
file.write(' {\n')
file.write(' if (o.get_rd_irf())\n')
self.dec_rrr(file,' ','idx_exe_jmpl_i0_rd')
file.write(' else\n')
self.dec_0rr(file,' ','idx_exe_jmpl_i0_g0')
file.write(' }\n')
file.write(' }\n')
file.write(' else\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self.c_code_end(file)
def gen_exe_tbl(self,file,mode):
for out in self.out:
for imm in self.imm:
if mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+'_'+imm+'_'+out+' */\n')
else:
self.gen_exe_rrI(file,mode,imm,out)
for imm in self.imm:
if mode == 'trc':
self.gen_exe_rrI(file,mode,imm)
elif mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_tct_'+self.name+'_'+imm+' */\n')
else:
file.write(' '+mode+'_tct_jmpl_'+imm+',\n')
def idx_exe_s(self,file):
for out in self.out:
for imm in self.imm:
self.idx_exe_s_name(file,'exe_'+self.opc+'_'+imm+'_'+out)
for imm in self.imm:
self.idx_exe_s_name(file,'tct_'+self.opc+'_'+imm)
def run_dec_p(self):
return 'run_dec_jmpl'
#============================================================================
# SS_tcc(cc,imm)
#
# Note: tcc in usermode only allows for trapno: 0..127, checked in trap handle
# Note: control transfer traps for tcc behave the same as bpcc with no annul.
#============================================================================
class SS_tcc(SS_InstrAsm):
def __init__(self,cc,ccr,imm):
SS_InstrAsm.__init__(self,'t'+cc+'_'+ccr+'_'+imm)
self.opc = 't'+cc
self.cc = cc
self.ccr = ccr
self.imm = imm
def run_exe_c(self,file):
file.write('#if defined(ARCH_X64)\n')
self.c_code_beg(file,'run_exe_')
self.test_icc(file,' ')
file.write(' {\n')
file.write(' uint64_t rs1 = s->get_irf(i->rs1);\n')
if (self.imm == 'i0'):
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
else:
file.write(' int rs2 = i->rs2;\n');
file.write(' int trap = (rs1 + rs2) & 0xFF;\n')
file.write(' return (s->trap)(pc,npc,s,i,(SS_Trap::Type)(trap+0x100));\n')
file.write(' }\n')
file.write(' else {\n')
file.write(' pc = npc;\n')
file.write(' s->npc = npc + 4;\n')
file.write(' return pc;\n')
file.write(' }\n')
self.c_code_end(file)
file.write('#else\n')
file.write('extern "C" SS_Vaddr run_exe_%s( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr* );\n' % (self.name))
file.write('#endif\n')
def run_exe_s(self,file):
self.asm_function(file,'run_exe_'+self.name)
if (self.cc == 'n'):
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,4,self.NPC)
self.retl_st_npc(file,self.NPC)
elif (self.cc == 'a'):
self.ld_rs1(file,'%g1')
self.ld_rs2(file,'%g2')
self.ld_irf(file,'%g1','%g1')
if (self.imm == 'i0'):
self.ld_irf(file,'%g2','%g2')
self.ld_trap(file,'%g5')
self.add(file,'%g1','%g2','%o4')
self.opr(file,'and','%o4',255,'%o4')
self.jmpl(file,'%g5','%g0','%g0')
self.add(file,'%o4',256,'%o4')
else:
self.ld_ccr(file,'%g3')
self.ld_rs1(file,'%g1')
self.ld_rs2(file,'%g2')
self.wr_ccr(file,'%g3')
self.ld_irf(file,'%g1','%g1')
if (self.imm == 'i0'):
self.ld_irf(file,'%g2','%g2')
self.ld_trap(file,'%g5')
self.branch(file,self.cc+',a','%'+self.ccr,'1f')
self.add(file,'%g1','%g2','%o4')
self.mov(file,self.NPC,self.PC)
self.add(file,self.NPC,4,self.NPC)
self.retl_st_npc(file,self.NPC)
file.write('1:\n')
self.opr(file,'and','%o4',255,'%o4')
self.jmpl(file,'%g5','%g0','%g0')
self.add(file,'%o4',256,'%o4')
self.asm_codesize(file,'run_exe_'+self.name)
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
if self.imm == 'i1':
file.write(' if (o.is_zero_10_8())\n')
file.write(' {\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
self.dec_0r8(file,' ','idx_tct_bp'+self.name[1:-2]+'a0')
file.write(' else\n')
self.dec_0r8(file,' ','idx_exe_'+self.name)
file.write(' }\n')
file.write(' else\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
else:
file.write(' if (o.is_zero_10_5())\n')
file.write(' {\n')
self.ill_ibe(file)
file.write(' if (s->pstate.tct())\n')
self.dec_0rr(file,' ','idx_tct_bp'+self.name[1:-2]+'a0')
file.write(' else\n')
self.dec_0rr(file,' ','idx_exe_'+self.name)
file.write(' }\n')
file.write(' else\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self.c_code_end(file)
def gen_exe_tbl(self,file,mode):
if mode == 'v8_run':
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self.name+' */\n')
else:
self.gen_exe_0rI(file,mode)
#============================================================================
# SS_done()
#============================================================================
class SS_done(SS_InstrCpp):
def __init__(self):
SS_InstrCpp.__init__(self,'done')
def run_exe_c(self,file):
self.c_code_beg(file,'run_exe_')
self.fail_chkpt(file)
file.write(' if (s->sim_state.priv() < SS_Strand::SS_PRIV)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::PRIVILEGED_OPCODE);\n')
file.write(' else if (s->tl() == 0)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' else if (s->pstate.tct())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' else\n')
file.write(' {\n')
file.write(' s->do_retry();\n')
file.write(' SS_Vaddr _npc = s->npc();\n')
file.write(' s->npc = _npc + 4;\n')
file.write(' return _npc;\n')
file.write(' }\n')
self.c_code_end(file)
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
file.write(' if (o.is_zero_18_0())\n')
file.write(' {\n')
self.ill_ibe(file)
self.dec_000(file,' ','idx_exe_'+self.name)
file.write(' }\n')
file.write(' else\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self.c_code_end(file)
def gen_exe_tbl(self,file,mode):
self.gen_exe_passthrough(file,mode)
#============================================================================
# SS_retry()
#============================================================================
class SS_retry(SS_InstrCpp):
def __init__(self):
SS_InstrCpp.__init__(self,'retry')
def run_exe_c(self,file):
self.c_code_beg(file,'run_exe_')
self.fail_chkpt(file)
file.write(' if (s->sim_state.priv() < SS_Strand::SS_PRIV)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::PRIVILEGED_OPCODE);\n')
file.write(' else if (s->tl() == 0)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' else if (s->pstate.tct())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' else\n')
file.write(' {\n')
file.write(' s->do_retry();\n')
file.write(' return s->pc();\n')
file.write(' }\n')
self.c_code_end(file)
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
file.write(' if (o.is_zero_18_0())\n')
file.write(' {\n')
self.ill_ibe(file)
self.dec_000(file,' ','idx_exe_'+self.name)
file.write(' }\n')
file.write(' else\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self.c_code_end(file)
def gen_exe_tbl(self,file,mode):
self.gen_exe_passthrough(file,mode)
#============================================================================
# SS_return()
#============================================================================
class SS_return(SS_InstrCpp):
def __init__(self):
SS_InstrCpp.__init__(self,'return')
self.opc = 'return'
self.imm = ['i0','i1']
def run_exe_c(self,file):
for imm in self.imm:
self.c_code_beg_name(file,'run_exe_'+self.name+'_'+imm)
self.fail_chkpt(file)
file.write('uint64_t r0,r1,r2,r3,r4,r5,r6,r7;')
file.write('uint64_t cwp = s->cwp();')
file.write('uint64_t canrestore = s->canrestore();')
file.write('r7 = s->irf[23];')
file.write('r6 = s->irf[22];')
file.write(' if (canrestore)\n')
file.write(' {\n')
if imm == 'i0':
file.write(' uint64_t ea = s->get_irf(i->rs1) + s->get_irf(i->rs2);\n')
else:
file.write(' uint64_t ea = s->get_irf(i->rs1) + i->rs2;\n')
file.write(' if (ea & 3)\n')
file.write(' return (s->inst_trap)(pc,npc,s,i,ea,SS_Trap::MEM_ADDRESS_NOT_ALIGNED);\n')
file.write(' else if (s->pstate.tct())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::CONTROL_TRANSFER_INSTRUCTION);\n')
file.write(' s->cwp_save();\n')
file.write(' cwp = cwp ? (cwp - 1) : s->max_wp();\n')
file.write(' s->cansave = (s->cansave() < s->max_wp()) ? (s->cansave() + 1) : 0;\n')
file.write(' s->canrestore = canrestore ? (canrestore - 1) : s->max_wp();\n')
file.write(' s->cwp = cwp;\n')
file.write(' s->cwp_load();')
file.write(' s->npc = ea; return npc;\n')
file.write(' }\n')
file.write(' else if (s->otherwin())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::fill_other(s->wstate.other()));\n')
file.write(' else\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::fill_normal(s->wstate.normal()));\n')
file.write('}\n\n')
def run_dec_c(self,file):
self.c_code_dec_beg(file,'run_dec_')
file.write(' i->flg = SS_Instr::NON_LSU;\n')
file.write(' if (o.get_rd())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' else if (o.get_i())\n')
file.write(' {\n')
self.ill_ibe(file)
self.dec_0r13(file,' ','idx_exe_'+self.name+'_i1')
file.write(' }\n')
file.write(' else if (o.is_zero_12_5())\n')
file.write(' {\n')
self.ill_ibe(file)
self.dec_0rr(file,' ','idx_exe_'+self.name+'_i0')
file.write(' }\n')
file.write(' else\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self.c_code_end(file)
def gen_exe_tbl(self,file,mode):
if mode == 'v8_run':
mode = 'run'
for imm in self.imm:
self.gen_exe_0rI(file,mode,imm)
#============================================================================
#============================================================================
ss_bp_icc = SS_InstrGroup('00_00100x_bp_icc',25,0x1f,2)
ss_bp_c01 = SS_InstrGroup('00_001011',25,0x1f,2)
ss_bp_xcc = SS_InstrGroup('00_00110x_bp_xcc',25,0x1f,2)
ss_bp_c11 = SS_InstrGroup('00_00111x',25,0x1f,2)
ss_bi = SS_InstrGroup('00_010xxx_bi',25,0x1f,8)
ss_br = SS_InstrGroup('00_011xxx_br',25,0x1f,8)
ss_fbp_fcc0 = SS_InstrGroup('00_10100x_fbp_fcc0',25,0x1f,2)
ss_fbp_fcc1 = SS_InstrGroup('00_10101x_fbp_fcc1',25,0x1f,2)
ss_fbp_fcc2 = SS_InstrGroup('00_10110x_fbp_fcc2',25,0x1f,2)
ss_fbp_fcc3 = SS_InstrGroup('00_10111x_fbp_fcc3',25,0x1f,2)
ss_fbi = SS_InstrGroup('00_110xxx_fbi',25,0x1f,8)
for cc,x in cond:
ss_bp_icc.append(SS_bp_a0(cc,'icc'))
ss_bp_c01.append(SS_ill())
ss_bp_xcc.append(SS_bp_a0(cc,'xcc'))
ss_bp_c11.append(SS_ill())
ss_bi.append(SS_bi_a0(cc))
for cc,x in cond:
ss_bp_icc.append(SS_bp_a1(cc,'icc'))
if setup.product == 'N2':
ss_bp_c01.append(SS_ill())
ss_bp_xcc.append(SS_bp_a1(cc,'xcc'))
ss_bp_c11.append(SS_ill())
ss_bi.append(SS_bi_a1(cc))
for cc,x in rcond:
if (cc != ''):
ss_br.append(SS_br_a0(cc))
else:
ss_br.append(SS_ill())
for cc,x in rcond:
if (cc != ''):
ss_br.append(SS_br_a1(cc))
else:
ss_br.append(SS_ill())
for cc,x in fcond:
ss_fbp_fcc0.append(SS_fbp_a0(cc,'fcc0'))
ss_fbp_fcc1.append(SS_fbp_a0(cc,'fcc1'))
ss_fbp_fcc2.append(SS_fbp_a0(cc,'fcc2'))
ss_fbp_fcc3.append(SS_fbp_a0(cc,'fcc3'))
ss_fbi.append(SS_fbi_a0(cc))
for cc,x in fcond:
ss_fbp_fcc0.append(SS_fbp_a1(cc,'fcc0'))
ss_fbp_fcc1.append(SS_fbp_a1(cc,'fcc1'))
ss_fbp_fcc2.append(SS_fbp_a1(cc,'fcc2'))
ss_fbp_fcc3.append(SS_fbp_a1(cc,'fcc3'))
ss_fbi.append(SS_fbi_a1(cc))
# done/retry
ss_done = SS_InstrGroup('10_111110_done',25,0x1f)
ss_done.append(SS_done())
ss_done.append(SS_retry())
for i in range(2,15):
ss_done.append(SS_ill())
if setup.product == 'N2':
ss_done.append(SS_ill())
for i in range(16,30):
ss_done.append(SS_ill())
if setup.product == 'N2':
ss_done.append(SS_ill())
ss_done.append(SS_ill())
# tcc
ss_tcc = SS_InstrGroup('10_111010_tcc',25,0x1f)
for cc,x in cond:
ss_tcc_iccr = SS_InstrGroup('10_111010_tcc_'+cc,11,7)
ss_tcc_iccr.append(SS_tcc(cc,'icc','i0'))
ss_tcc_iccr.append(SS_ill())
ss_tcc_iccr.append(SS_tcc(cc,'xcc','i0'))
ss_tcc_iccr.append(SS_ill())
ss_tcc_iccr.append(SS_tcc(cc,'icc','i1'))
ss_tcc_iccr.append(SS_ill())
ss_tcc_iccr.append(SS_tcc(cc,'xcc','i1'))
ss_tcc_iccr.append(SS_ill())
ss_tcc.append(ss_tcc_iccr)
for cc,x in cond:
ss_tcc.append(SS_ill())