r500/regs/assembler/emitter.py

113 lines
3.7 KiB
Python

from assembler.keywords import ME, VE, KW
from assembler.parser import Instruction, DestinationOp, Source
import pvs_dst
import pvs_src
import pvs_dst_bits
import pvs_src_bits
def we_x(s):
return int(0 in s)
def we_y(s):
return int(1 in s)
def we_z(s):
return int(2 in s)
def we_w(s):
return int(3 in s)
def dst_reg_type(kw):
if kw == KW.temporary:
return pvs_dst_bits.PVS_DST_REG_gen["TEMPORARY"]
elif kw == KW.a0:
return pvs_dst_bits.PVS_DST_REG_gen["A0"]
elif kw == KW.out:
return pvs_dst_bits.PVS_DST_REG_gen["OUT"]
elif kw == KW.out_repl_x:
return pvs_dst_bits.PVS_DST_REG_gen["OUT_REPL_X"]
elif kw == KW.alt_temporary:
return pvs_dst_bits.PVS_DST_REG_gen["ALT_TEMPORARY"]
elif kw == KW.input:
return pvs_dst_bits.PVS_DST_REG_gen["INPUT"]
else:
assert not "Invalid PVS_DST_REG", kw
def emit_destination_op(dst_op: DestinationOp):
assert type(dst_op.opcode) in {ME, VE}
math_inst = int(type(dst_op.opcode) is ME)
value = (
pvs_dst.OPCODE_gen(dst_op.opcode.value)
| pvs_dst.MATH_INST_gen(math_inst)
| pvs_dst.REG_TYPE_gen(dst_reg_type(dst_op.type))
| pvs_dst.OFFSET_gen(dst_op.offset)
| pvs_dst.WE_X_gen(we_x(dst_op.write_enable))
| pvs_dst.WE_Y_gen(we_y(dst_op.write_enable))
| pvs_dst.WE_Z_gen(we_z(dst_op.write_enable))
| pvs_dst.WE_W_gen(we_w(dst_op.write_enable))
)
yield value
def src_reg_type(kw):
if kw == KW.temporary:
return pvs_src_bits.PVS_SRC_REG_TYPE_gen["PVS_SRC_REG_TEMPORARY"]
elif kw == KW.input:
return pvs_src_bits.PVS_SRC_REG_TYPE_gen["PVS_SRC_REG_INPUT"]
elif kw == KW.constant:
return pvs_src_bits.PVS_SRC_REG_TYPE_gen["PVS_SRC_REG_CONSTANT"]
elif kw == KW.alt_temporary:
return pvs_src_bits.PVS_SRC_REG_TYPE_gen["PVS_SRC_REG_ALT_TEMPORARY"]
else:
assert not "Invalid PVS_SRC_REG", kw
def emit_source(src: Source, prev: Source):
if src is not None:
value = (
pvs_src.REG_TYPE_gen(src_reg_type(src.type))
| pvs_src.OFFSET_gen(src.offset)
| pvs_src.SWIZZLE_X_gen(src.swizzle.select[0])
| pvs_src.SWIZZLE_Y_gen(src.swizzle.select[1])
| pvs_src.SWIZZLE_Z_gen(src.swizzle.select[2])
| pvs_src.SWIZZLE_W_gen(src.swizzle.select[3])
| pvs_src.MODIFIER_X_gen(int(src.swizzle.modifier[0]))
| pvs_src.MODIFIER_Y_gen(int(src.swizzle.modifier[1]))
| pvs_src.MODIFIER_Z_gen(int(src.swizzle.modifier[2]))
| pvs_src.MODIFIER_W_gen(int(src.swizzle.modifier[3]))
)
else:
assert prev is not None
value = (
pvs_src.REG_TYPE_gen(src_reg_type(prev.type))
| pvs_src.OFFSET_gen(prev.offset)
| pvs_src.SWIZZLE_X_gen(7)
| pvs_src.SWIZZLE_Y_gen(7)
| pvs_src.SWIZZLE_Z_gen(7)
| pvs_src.SWIZZLE_W_gen(7)
| pvs_src.MODIFIER_X_gen(0)
| pvs_src.MODIFIER_Y_gen(0)
| pvs_src.MODIFIER_Z_gen(0)
| pvs_src.MODIFIER_W_gen(0)
)
yield value
def prev_source(ins, ix):
if ix == 0:
assert ins.source0 is not None
return ins.source0
elif ix == 1:
return ins.source0
elif ix == 2:
if ins.source1 is not None:
return ins.source1
else:
return ins.source0
else:
assert False, ix
def emit_instruction(ins: Instruction):
yield from emit_destination_op(ins.destination_op)
yield from emit_source(ins.source0, prev_source(ins, 0))
yield from emit_source(ins.source1, prev_source(ins, 1))
yield from emit_source(ins.source2, prev_source(ins, 2))