quakeforge/libs/gamecode/extend.py
Bill Currie d9d0a80752 [gamecode] Add an extend instruction
The extend instruction is for loading narrower data types into wider
data types, eg, single element into 2, 3, or 4 element types, with a
small set of extension schemes: 0, 1, -1, copy (for 1->any and 2 -> 4).
Possibly most importantly, it works with unaligned data.

Progress towards #30
2022-08-18 18:18:19 +09:00

77 lines
2.2 KiB
Python

print("""// encoding is teemmm
// t = 0: 32-bit, t = 1: 64-bit
// e = 00: 0
// e = 01: 1.0
// e = 10: copy (1-n, 2-4, otherwise 0)
// e = 11: -1.0
// mmm = 000: 1 -> 2
// mmm = 001: 1 -> 3
// mmm = 010: 1 -> 4
// mmm = 011: 2 -> 3
// mmm = 100: 2 -> 4
// mmm = 101: 3 -> 4
// mmm = 110: reserved
// mmm = 111: reserved
""")
types = [
["ivec2", "ivec3", "ivec4", "ivec3", "ivec4", "ivec4"],
["lvec2", "lvec3", "lvec4", "lvec3", "lvec4", "lvec4"],
]
src_types = [
["int", "int", "int", "ivec2", "ivec2", "ivec3"],
["long", "long", "long", "lvec2", "lvec2", "lvec3"],
]
extend = [
["0", "INT32_C(0x3f800000)", "0", "INT32_C(0xbf800000)"],
["0", "INT64_C(0x3ff0000000000000)", "0", "INT64_C(0xbff0000000000000)"],
]
def case_str(type, ext, mode):
case = (type << 5) | (ext << 3) | (mode)
return f"case {case:03o}:"
def dst_str(type, ext, mode):
return f"OPC({types[type][mode]})"
def cast_str(type, ext, mode):
return f"(pr_{types[type][mode]}_t)"
def init_str(type, ext, mode):
ext_str = extend[type][ext]
src = f"OPA({src_types[type][mode]})"
if mode == 0:
if ext == 2:
ext_str = src
return f"{src}, {ext_str}"
elif mode == 1:
if ext == 2:
ext_str = src
return f"{src}, {ext_str}, {ext_str}"
elif mode == 2:
if ext == 2:
ext_str = src
return f"{src}, {ext_str}, {ext_str}, {ext_str}"
elif mode == 3:
return f"{src}[0], {src}[1], {ext_str}"
elif mode == 4:
if ext == 2:
return f"{src}[0], {src}[1], {src}[0], {src}[1]"
else:
return f"{src}[0], {src}[1], {ext_str}, {ext_str}"
elif mode == 5:
return f"{src}[0], {src}[1], {src}[2], {ext_str}"
for type in range(2):
for ext in range(4):
for mode in range(6): # 6, 7 are reserved
case = case_str(type, ext, mode)
dst = dst_str(type, ext, mode)
cast = cast_str(type, ext, mode)
init = init_str(type, ext, mode)
if mode in [1, 3]:
print(f"{case} VectorSet({init}, {dst}); break;");
else:
print(f"{case} {dst} = {cast} {{ {init} }}; break;");