1#!src/build/run_python 2# 3# Copyright (C) 2014 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import itertools 19import json 20import sys 21 22import gen_asm_x86 23 24 25# Enable to avoid cycles. Only use one register combo for tests. 26fast_mode = False 27 28 29def main(argv): 30 # Usage: gen_asm.tests_py <assembler_ref.S> 31 # <assembler_test.cc> 32 # <def_common> 33 # <def_arch> 34 att_assembler_file_name = argv[1] 35 arc_assembler_file_name = argv[2] 36 # Generate empty files if we don't have assembler files to test. 37 if len(argv) <= 4: 38 with open(att_assembler_file_name, 'w') as att_assembler_file: 39 pass 40 with open(arc_assembler_file_name, 'w') as arc_assembler_file: 41 pass 42 return 0 43 common_defs = gen_asm_x86._load_asm_defs(argv[3]) 44 arch_defs = gen_asm_x86._load_asm_defs(argv[4]) 45 46 fast_mode = globals()["fast_mode"] 47 if len(argv) > 5 and argv[5] == '--fast': 48 fast_mode = True 49 50 with open(argv[4]) as arch_def: 51 obj = json.load(arch_def) 52 arch = obj.get('arch') 53 assert arch in ('x86_32', 'x86_64') 54 _update_arguments(arch == 'x86_64') 55 56 with open(att_assembler_file_name, 'w') as att_assembler_file: 57 print('.globl berberis_gnu_as_output_start_%s' % arch, 58 file=att_assembler_file) 59 print('.globl berberis_gnu_as_output_end_%s' % arch, 60 file=att_assembler_file) 61 print('.data', file=att_assembler_file) 62 print('berberis_gnu_as_output_start_%s:' % arch, 63 file=att_assembler_file) 64 print('.code%d' % (32 if arch == 'x86_32' else 64), file=att_assembler_file) 65 _gen_att_assembler(att_assembler_file, common_defs, fast_mode) 66 _gen_att_assembler(att_assembler_file, arch_defs, fast_mode) 67 print('berberis_gnu_as_output_end_%s:' % arch, file=att_assembler_file) 68 69 with open(arc_assembler_file_name, 'w') as arc_assembler_file: 70 print('#include "berberis/assembler/%s.h"' % (arch), file=arc_assembler_file) 71 print('namespace berberis {', file=arc_assembler_file) 72 print('namespace %s {' % (arch), file=arc_assembler_file) 73 _gen_arc_generators(arc_assembler_file) 74 _gen_arc_assembler(arc_assembler_file, 'Common', common_defs, fast_mode) 75 _gen_arc_assembler(arc_assembler_file, 'Arch', arch_defs, fast_mode) 76 print('} // namespace %s' % (arch), file=arc_assembler_file) 77 print('} // namespace berberis', file=arc_assembler_file) 78 return 0 79 80 81sample_att_arguments = { 82 # Note: st(0) is not tested on purpose: many instructions have ambiguity 83 # where st(0) to st(0) version can be encoded in two different ways and both 84 # work fine, but assemblers produce different versions! 85 # Rather than try to match everything perfectly we limit ourselves to st(1), 86 # st(2), and st(4) which ensures that all bits are ancoded correctly. 87 'RegX87': ('%st(1)', '%st(2)', '%st(4)'), 88 'Imm2': ('$0', '$1', '$2', '$3'), 89 'Imm8': ('$-1', '$0', '$1', '$2'), 90 'Imm16': ('$-1', '$0', '$1', '$2', '$256'), 91 'Imm32': ('$-1', '$0', '$1', '$2', '$256', '$65536') 92} 93 94sample_att_arguments_x86_32 = { 95 # Note: accumulator comes last to ensure that --fast version doesn't pick it, 96 # except as accumulator. That way we test both instruction where accumulator 97 # is encoded specially (such as “add %al,$1”) and instructios where 98 # accumulator is not used (such as “add %cl,$1”. 99 'GeneralReg8': ('%CL', '%DL', '%BL', '%AL'), 100 'GeneralReg16': ('%CX', '%DX', '%BX', '%SP', '%BP', '%SI', '%DI', '%AX'), 101 'GeneralReg32': ('%ECX', '%EDX', '%EBX', '%ESP', 102 '%EBP', '%ESI', '%EDI', '%EAX'), 103 'VecReg128': tuple('%%XMM%d' % N for N in (0, 4, 7)), 104 'XmmReg': tuple('%%XMM%d' % N for N in (0, 4, 7)), 105 'FpReg32': tuple('%%XMM%d' % N for N in range(8)), 106 'FpReg64': tuple('%%XMM%d' % N for N in range(8)), 107 'Label': ('0b', '1b', '2f'), 108} 109 110sample_att_arguments_x86_64 = { 111 'Imm64': ('$-1', '$0', '$1', '$2', '$256', '$65536', '$4294967296'), 112 # Note: accumulator comes last to ensure that --fast version doesn't pick it, 113 # except as accumulator. That way we test both instruction where accumulator 114 # is encoded specially (such as “add %al,$1”) and instructios where 115 # accumulator is not used (such as “add %cl,$1”. 116 'GeneralReg8': ('%CL', '%DL', '%BL', '%SPL', 117 '%BPL', '%SIL', '%DIL', '%R8B', 118 '%R9B', '%R10B', '%R11B', '%R12B', 119 '%R13B', '%R14B', '%R15B', '%AL', ), 120 'GeneralReg16': ('%CX', '%DX', '%BX', '%SP', 121 '%BP', '%SI', '%DI', '%R8W', 122 '%R9W', '%R10W', '%R11W', '%R12W', 123 '%R13W', '%R14W', '%R15W', '%AX'), 124 'GeneralReg32': ('%ECX', '%EDX', '%EBX', '%ESP', 125 '%EBP', '%ESI', '%EDI', '%R8D', 126 '%R9D', '%R10D', '%R11D', '%R12D', 127 '%R13D', '%R14D', '%R15D', '%EAX'), 128 'GeneralReg64': ('%RCX', '%RDX', '%RBX', '%RSP', 129 '%RBP', '%RSI', '%RDI', '%R8', 130 '%R9', '%R10', '%R11', '%R12', 131 '%R13', '%R14', '%R15', '%RAX',), 132 'VecReg128': tuple('%%XMM%d' % N for N in range(0, 16, 5)), 133 'XmmReg': tuple('%%XMM%d' % N for N in range(0, 16, 5)), 134 'FpReg32': tuple('%%XMM%d' % N for N in range(16)), 135 'FpReg64': tuple('%%XMM%d' % N for N in range(16)), 136 'Label': ('0b', '1b', '2f'), 137} 138 139sample_arc_arguments = { 140 # Note: st(0) is not tested on purpose: many instructions have ambiguity 141 # where st(0) to st(0) version can be encoded in two different ways and both 142 # work fine, but assemblers produce different versions! 143 # Rather than try to match everything perfectly we limit ourselves to st(1), 144 # st(2), and st(4) which ensures that all bits are ancoded correctly. 145 'RegX87': ('Assembler::st1', 'Assembler::st2', 'Assembler::st4'), 146 'Imm2': ('0', '1', '2', '3'), 147 'Imm8': ('-1', '0', '1', '2'), 148 'Imm16': ('-1', '0', '1', '2', '256'), 149 'Imm32': ('-1', '0', '1', '2', '256', '65536'), 150 'Cond': ('Assembler::Condition::kOverflow', 'Assembler::Condition::kNoOverflow', 151 'Assembler::Condition::kBelow', 'Assembler::Condition::kAboveEqual', 152 'Assembler::Condition::kEqual', 'Assembler::Condition::kNotEqual', 153 'Assembler::Condition::kBelowEqual', 'Assembler::Condition::kAbove', 154 'Assembler::Condition::kNegative', 'Assembler::Condition::kPositive', 155 'Assembler::Condition::kParityEven', 'Assembler::Condition::kParityOdd', 156 'Assembler::Condition::kLess', 'Assembler::Condition::kGreaterEqual', 157 'Assembler::Condition::kLessEqual', 'Assembler::Condition::kGreater'), 158} 159 160# Note: have to match sample_att_arguments_x86_32. 161# Read comment there about why accumulator is last. 162gp_registers_32 = ('Assembler::ecx', 'Assembler::edx', 163 'Assembler::ebx', 'Assembler::esp', 164 'Assembler::ebp', 'Assembler::esi', 165 'Assembler::edi', 'Assembler::eax', ) 166 167# Note: have to match sample_att_arguments_x86_32. 168# Read comment there about why accumulator is last. 169gp_registers_64 = ('Assembler::rcx', 'Assembler::rdx', 170 'Assembler::rbx', 'Assembler::rsp', 171 'Assembler::rbp', 'Assembler::rsi', 172 'Assembler::rdi', 'Assembler::r8', 173 'Assembler::r9', 'Assembler::r10', 174 'Assembler::r11', 'Assembler::r12', 175 'Assembler::r13', 'Assembler::r14', 176 'Assembler::r15', 'Assembler::rax',) 177 178sample_arc_arguments_x86_32 = { 179 # Note: have to match sample_att_arguments_x86_32. 180 # Read comment there about why accumulator is last. 181 'GeneralReg8': ('Assembler::ecx', 'Assembler::edx', 182 'Assembler::ebx', 'Assembler::eax'), 183 'GeneralReg16': gp_registers_32, 184 'GeneralReg32': gp_registers_32, 185 'VecReg128': tuple('Assembler::xmm%d' % N for N in (0, 4, 7)), 186 'XmmReg': tuple('Assembler::xmm%d' % N for N in (0, 4, 7)), 187 'FpReg32': tuple('Assembler::xmm%d' % N for N in range(8)), 188 'FpReg64': tuple('Assembler::xmm%d' % N for N in range(8)), 189} 190 191sample_arc_arguments_x86_64 = { 192 'Imm64': ('-1', '0', '1', '2', '256', '65536', '4294967296LL'), 193 'GeneralReg8': gp_registers_64, 194 'GeneralReg16': gp_registers_64, 195 'GeneralReg32': gp_registers_64, 196 'GeneralReg64': gp_registers_64, 197 'VecReg128': tuple('Assembler::xmm%d' % N for N in range(0, 16, 5)), 198 'XmmReg': tuple('Assembler::xmm%d' % N for N in range(0, 16, 5)), 199 'FpReg32': tuple('Assembler::xmm%d' % N for N in range(16)), 200 'FpReg64': tuple('Assembler::xmm%d' % N for N in range(16)), 201} 202 203MNEMO_TO_ASM = { 204 'MOVDQ': 'MOVAPS', 205 'MOVSXBL': 'MOVSBL', 206 'MOVSXBQ': 'MOVSBQ', 207 'MOVSXWL': 'MOVSWL', 208 'MOVSXWQ': 'MOVSWQ', 209 'MOVSXLQ': 'MOVSLQ', 210 'MOVZXBL': 'MOVZBL', 211 'MOVZXBQ': 'MOVZBQ', 212 'MOVZXWL': 'MOVZWL', 213 'MOVZXWQ': 'MOVZWQ', 214 'VCVTPD2DQ': 'VCVTPD2DQX', 215 'VCVTPD2PS': 'VCVTPD2PSX', 216 'VCVTTPD2DQ': 'VCVTTPD2DQX' 217} 218 219FIXED_REGISTER_CLASSES = ( 220 'AL', 'AX', 'EAX', 'RAX', 221 'CL', 'ECX', 'RCX', 'ST', 'ST1', 222 'DX', 'EDX', 'RDX', 'CC', 223 'BX', 'EBX', 'RBX', 'SW', 224 'EBP', 'RSP', 'FLAGS' 225) 226 227 228def _update_arguments(x86_64): 229 if x86_64: 230 addr = 'GeneralReg64' 231 sample_att_arguments.update(sample_att_arguments_x86_64) 232 sample_arc_arguments_add = sample_arc_arguments_x86_64 233 else: 234 addr = 'GeneralReg32' 235 sample_att_arguments.update(sample_att_arguments_x86_32) 236 sample_arc_arguments_add = sample_arc_arguments_x86_32 237 for key, values in sample_arc_arguments_add.items(): 238 sample_arc_arguments[key] = values 239 addrs = ['0'] 240 addrs += ['(%s)' % reg for reg in sample_att_arguments[addr]] 241 addrs += ['%s(,%s%s)' % (offset, index, scale) 242 for offset in ('', '64', '32768') 243 for index in sample_att_arguments[addr] 244 for scale in ('', ',2', ',4', ',8') 245 if index not in ('%ESP', '%RSP')] 246 addrs += ['%s(%s,%s%s)' % (offset, base, index, scale) 247 for offset in ('', '64', '32768') 248 for base in sample_att_arguments[addr] 249 for index in sample_att_arguments[addr] 250 for scale in ('', ',2', ',4', ',8') 251 if index not in ('%ESP', '%RSP')] 252 for mem_arg in ('Mem8', 'Mem16', 'Mem32', 'Mem64', 'Mem128', 253 'MemX87', 'MemX8716', 'MemX8732', 'MemX8764', 'MemX8780', 254 'VecMem32', 'VecMem64', 'VecMem128'): 255 sample_att_arguments[mem_arg] = tuple(addrs) 256 257 sample_att_arguments['GeneralReg'] = sample_att_arguments[addr] 258 259 def peel_constructor(s): 260 return s.split('(', 1)[1][:-1] if '(' in s else s 261 262 addrs = ['Assembler::Operand()'] 263 addrs += ['{.base = %s}' % peel_constructor(reg) 264 for reg in sample_arc_arguments[addr]] 265 addrs += ['{.index = %s, .scale = Assembler::kTimes%s, .disp = %d}' % 266 (peel_constructor(index), scale, disp) 267 for disp in (0, 64, 32768) 268 for index in sample_arc_arguments[addr] 269 for scale in ('One', 'Two', 'Four', 'Eight') 270 if 'Assembler::esp' not in index and 'Assembler::rsp' not in index] 271 addrs += ['{.base = %s, .index = %s, .scale = Assembler::kTimes%s, .disp = %d}' % 272 (peel_constructor(base), peel_constructor(index), scale, disp) 273 for disp in (0, 64, 32768) 274 for base in sample_arc_arguments[addr] 275 for index in sample_arc_arguments[addr] 276 for scale in ('One', 'Two', 'Four', 'Eight') 277 if 'Assembler::esp' not in index and 'Assembler::rsp' not in index] 278 for mem_arg in ('Mem8', 'Mem16', 'Mem32', 'Mem64', 'Mem128', 279 'MemX87', 'MemX8716', 'MemX8732', 'MemX8764', 'MemX8780', 280 'VecMem32', 'VecMem64', 'VecMem128'): 281 sample_arc_arguments[mem_arg] = tuple(addrs) 282 283 sample_arc_arguments['GeneralReg'] = sample_arc_arguments[addr] 284 285 286def _gen_att_assembler(file, insns, fast_mode): 287 for insn in insns: 288 arc_name = insn['asm'] 289 insn_name = insn['mnemo'] 290 if len(insn['args']) and insn['args'][0]['class'] == 'Cond': 291 if insn_name in ('CMOVW', 'CMOVL', 'CMOVQ'): 292 insn_name = 'CMOV' 293 else: 294 assert insn_name.endswith('CC') 295 insn_name = insn_name[:-2] 296 for insn_suffix in ('O', 'NO', 'B', 'AE', 'E', 'NE', 'BE', 'A', 297 'S', 'NS', 'P', 'NP', 'L', 'GE', 'LE', 'G'): 298 _gen_att_instruction_variants( 299 file, arc_name, insn_name + insn_suffix, insn['args'], fast_mode) 300 elif arc_name == 'Call' and insn['args'][1]['class'] != 'Label': 301 _gen_att_call_variants(file, insn['args'], fast_mode) 302 else: 303 _gen_att_instruction_variants( 304 file, arc_name, insn_name, insn['args'], fast_mode) 305 306 307def _gen_att_instruction_variants( 308 file, arc_name, insn_name, insn_args, fast_mode): 309 if insn_name in MNEMO_TO_ASM: 310 insn_name = MNEMO_TO_ASM[insn_name] 311 insn_sample_args = [] 312 label_present = False 313 if arc_name.endswith('ByOne'): 314 assert insn_name.endswith('BYONE') 315 insn_name = insn_name[:-5] 316 elif arc_name.endswith('Imm2'): 317 assert insn_name.endswith('IMM2') 318 insn_name = insn_name[:-4] 319 elif arc_name.endswith('Imm8'): 320 assert insn_name.endswith('IMM8') 321 insn_name = insn_name[:-4] 322 elif arc_name.endswith('Accumulator'): 323 assert insn_name.endswith('ACCUMULATOR') 324 insn_name = insn_name[:-11] 325 elif arc_name.endswith('ByCl'): 326 assert insn_name.endswith('BYCL') 327 insn_name = insn_name[:-4] 328 elif arc_name.endswith('FromSt'): 329 assert insn_name.endswith('FROMST') 330 insn_name = insn_name[:-6] 331 elif arc_name.endswith('ToSt'): 332 assert insn_name.endswith('TOST') 333 insn_name = insn_name[:-4] 334 for arg_nr, insn_arg in enumerate(insn_args): 335 arg_class = insn_arg['class'] 336 if arg_class == 'Cond': 337 # This argument was already embedded into the name of instruction. 338 continue 339 if arg_class == 'Label': 340 label_present = True 341 if arg_class in ('AL', 'AX', 'EAX', 'RAX') and ( 342 arc_name.endswith('Accumulator') or arc_name == "Fnstsw"): 343 arg_variants = ('%%%s' % arg_class,) 344 elif arg_class == 'CL' and arc_name.endswith('ByCl'): 345 arg_variants = ('%CL',) 346 elif arg_class == 'ST' and (arc_name.endswith('FromSt') or arc_name.endswith('ToSt')): 347 arg_variants = ('%ST',) 348 elif arg_class == 'GeneralReg' and insn_name not in ('PUSH', 'POP'): 349 arg_variants = tuple('*%s' % reg for reg in sample_att_arguments['GeneralReg']) 350 elif arg_class[:3] == 'Imm' and insn_name in ( 351 'PSLLW', 'PSRAW', 'PSRLW', 'PSLLD', 'PSRAD', 'PSRLD', 352 'PSLLQ', 'PSRLQ', 'PSLLDQ', 'PSRLDQ', 353 'RCLB', 'RCLW', 'RCLL', 'RCLQ', 'RCRB', 'RCRW', 'RCRL', 'RCRQ', 354 'ROLB', 'ROLW', 'ROLL', 'ROLQ', 'RORB', 'RORW', 'RORL', 'RORQ', 355 'SHLB', 'SHLW', 'SHLL', 'SHLQ', 'SHRB', 'SHRW', 'SHRL', 'SHRQ', 356 'SARB', 'SARW', 'SARL', 'SARQ', 'BTCB', 'BTCW', 'BTCL', 'BTCQ'): 357 arg_variants = sample_att_arguments[insn_arg['class']][1:] 358 elif ((arg_class == 'Mem32' and insn_name in ('JMPL', 'CALLL')) or 359 (arg_class == 'VecMem64' and insn_name in ('JMPQ', 'CALLQ'))): 360 arg_variants = tuple('*%s' % reg for reg in sample_att_arguments[insn_arg['class']]) 361 elif arg_class in FIXED_REGISTER_CLASSES: 362 # Note: arguments from FIXED_REGISTER_CLASSES are implicit in AT&T assembler 363 # (except for accumulator in some instructions). Skip them. 364 continue 365 else: 366 arg_variants = sample_att_arguments[insn_arg['class']] 367 # Some instructions have special encodings with certain immediates 368 # (e.g. shifts by 1, introduced in 8086, are encoded differently than 369 # shifts by 2, introduced in 80186). 370 # Keep all variants even in --fast mode. 371 if fast_mode and not arg_class.startswith('Imm'): 372 # In --fast mode we want to keep only one variant, but it's important for 373 # us to pick different registers for diffetent position. 374 # This way we are testting “vmfaddps %xmm0, %xmm1, %xmm2, %xmm3” instead 375 # of “vmfaddps %xmm0, %xmm0, %xmm0, %xmm0” which is important to detect 376 # cases where operands are specified in a wrong order in JSON. 377 arg_variants = (arg_variants[arg_nr % len(arg_variants)],) 378 insn_sample_args.append(arg_variants) 379 for insn_args in itertools.product(*insn_sample_args): 380 fixed_name = insn_name 381 if insn_name == 'MOVQ' and not '(' in insn_args[0] and '%' in insn_args[0]: 382 # This is rare case where ARC code emitter produces code more optimal than 383 # GNU assembler. Reproduce that optimization here. 384 if insn_args[1][0] == '$' and insn_args[1] not in ('$-1', '$4294967296'): 385 fixed_name = 'MOVL' 386 # Make 32-bit version of register name. High registers need to add 387 # 'D' suffix, for low ones we need to replace 'R' with 'E'. 388 if insn_args[0] in ('%R8', '%R9', '%R10', '%R11', 389 '%R12', '%R13', '%R14', '%R15'): 390 insn_args = (insn_args[0] + 'D',) + insn_args[1:] 391 else: 392 insn_args = ('%E' + insn_args[0][2:],) + insn_args[1:] 393 if insn_name[0:4] == 'LOCK': 394 # TODO(b/161986409): replace '\n' with ' ' when clang would be fixed. 395 fixed_name = '%s\n%s' % (insn_name[0:4], insn_name[4:]) 396 fixed_name = { 397 # GNU disassembler accepts these instructions, but not Clang assembler. 398 'FNDISI': '.byte 0xdb, 0xe1', 399 'FNENI': '.byte 0xdb, 0xe0', 400 'FNSETPM': '.byte 0xdb, 0xe4', 401 }.get(fixed_name, fixed_name) 402 if label_present: 403 print('.p2align 5, 0x90', file=file) 404 print('0:', file=file) 405 for _ in range(256): 406 print('nop', file=file) 407 print('1:', file=file) 408 print('%s %s' % (fixed_name, ', '.join(reversed(insn_args))), file=file) 409 if label_present: 410 for _ in range(256): 411 print('nop', file=file) 412 print('2:', file=file) 413 414 415def _gen_att_call_variants(file, call_args, fast_mode): 416 assert len(call_args) == 2 417 assert call_args[0]['class'] == 'RSP' 418 assert call_args[1]['class'] == 'GeneralReg' 419 arg_variants = sample_att_arguments['GeneralReg'] 420 if fast_mode: 421 arg_variants = (arg_variants[1],) 422 for call_arg in arg_variants: 423 print('CALL *%s' % call_arg, file=file) 424 425 426def _gen_arc_generators(file): 427 for arg_class, arc_args in sample_arc_arguments.items(): 428 if arg_class == 'Label': 429 continue 430 arg_type = _argument_class_to_arc_type(arg_class) 431 print('%s* %sArgs() {' % (arg_type, arg_class), file=file) 432 print(' static %s* arg_list;' % arg_type, file=file) 433 print(' if (!arg_list) {', file=file) 434 print(' arg_list = reinterpret_cast<%s*>(malloc(%d * sizeof(%s)));' % 435 (arg_type, len(arc_args), arg_type), file=file) 436 for arg_nr, arg in enumerate(arc_args): 437 print(' arg_list[%d] = %s;' % (arg_nr, arg), file=file) 438 print(' }', file=file) 439 print(' return arg_list;', file=file) 440 print('}', file=file) 441 print('', file=file) 442 443 444def _gen_arc_assembler(file, insn_kind, insns, fast_mode): 445 for insn in insns: 446 _gen_arc_instruction_variants(file, insn['asm'], insn['args'], fast_mode) 447 print('void GenInsns%s(Assembler* as) {' % 448 insn_kind, file=file) 449 for insn in insns: 450 classes = [insn_arg['class'] for insn_arg in insn['args']] 451 print(' %s_%s(as);' % (insn['asm'], '_'.join(classes)), file=file) 452 if not insns: 453 print(' UNUSED(as);', file=file) 454 print('}', file=file) 455 print('', file=file) 456 457 458def _gen_arc_instruction_variants(file, arc_name, insn_args, fast_mode): 459 classes = [insn_arg['class'] for insn_arg in insn_args] 460 print('void %s_%s(Assembler* as) {' % 461 (arc_name, '_'.join(classes)), file=file) 462 label_present = False 463 arg_type_count = 0 464 indent = '' 465 for arg_nr, insn_arg in enumerate(insn_args): 466 arg_class = insn_arg['class'] 467 arg_ref = '*' 468 indent = ' ' * (2 * arg_type_count) 469 if arg_class == 'Label': 470 label_present = True 471 print('%s Assembler::Label* labels[3];' % indent, file=file) 472 args_generator = 'labels' 473 arg_ref = '**' 474 else: 475 args_generator = '%sArgs()' % arg_class 476 if arg_class not in FIXED_REGISTER_CLASSES: 477 arg_type = _argument_class_to_arc_type(arg_class) 478 if arg_class == 'Label': 479 arg_choices = 3 480 else: 481 arg_choices = len(sample_arc_arguments[arg_class]) 482 arg_shift = '' 483 if arg_class[:3] == 'Imm' and arc_name in ( 484 'Psllw', 'Psraw', 'Psrlw', 'Pslld', 'Psrad', 'Psrld', 485 'Psllq', 'Psrlq', 'Pslldq', 'Psrldq', 486 'Rclb', 'Rclw', 'Rcll', 'Rclq', 'Rcrb', 'Rcrw', 'Rcrl', 'Rcrq', 487 'Rolb', 'Rolw', 'Roll', 'Rolq', 'Rorb', 'Rorw', 'Rorl', 'Rorq', 488 'Shlb', 'Shlw', 'Shll', 'Shlq', 'Shrb', 'Shrw', 'Shrl', 'Shrq', 489 'Sarb', 'Sarw', 'Sarl', 'Sarq', 'Btcb', 'Btcw', 'Btcl', 'Btcq'): 490 arg_choices = arg_choices - 1 491 arg_shift = ' + 1' 492 # See notes about fast_mode handing in _gen_att_instruction_variants. 493 if fast_mode and not arg_class.startswith('Imm') and not arg_class == 'Cond': 494 print('%s %s %sarg%d = %s%s + %d;' % 495 (indent, arg_type, arg_ref, arg_nr, args_generator, arg_shift, 496 arg_nr % arg_choices), 497 file=file) 498 else: 499 arg_type_count += 1 500 print('%s for (%s %sarg%d = %s%s, %sarg%d_list = arg%d;' 501 ' arg%d != arg%d_list + %d; ++arg%d) {' % 502 (indent, arg_type, arg_ref, arg_nr, args_generator, arg_shift, 503 arg_ref, arg_nr, arg_nr, arg_nr, arg_nr, arg_choices, arg_nr), 504 file=file) 505 indent = ' ' * (2 * arg_type_count) 506 if label_present: 507 print('%s labels[0] = as->MakeLabel();' % indent, file=file) 508 print('%s labels[1] = as->MakeLabel();' % indent, file=file) 509 print('%s labels[2] = as->MakeLabel();' % indent, file=file) 510 print('%s // Don\'t use as->Align(32) for compatibility with GNU as' 511 % indent, file=file) 512 print('%s while (as->pc()%%32) as->Nop();' % indent, file=file) 513 print('%s as->Bind(labels[0]);' % indent, file=file) 514 print('%s for (int nr=0; nr < 256; ++nr)' % indent, file=file) 515 print('%s as->Nop();' % indent, file=file) 516 print('%s as->Bind(labels[1]);' % indent, file=file) 517 print('%s as->%s(%s);' % 518 (indent, 519 arc_name, 520 ', '.join(( 521 '%sarg%d' % ('*' if arg['class'] != 'Label' else '**', nr) 522 for nr, arg in enumerate(insn_args) 523 if arg['class'] not in FIXED_REGISTER_CLASSES))), 524 file=file) 525 if label_present: 526 print('%s for (int nr=0; nr < 256; ++nr)' % indent, file=file) 527 print('%s as->Nop();' % indent, file=file) 528 print('%s as->Bind(labels[2]);' % indent, file=file) 529 for arg_nr in range(arg_type_count, 0, -1): 530 print('%s}' % (' ' * (2 * arg_nr)), file=file) 531 print('}', file=file) 532 print('', file=file) 533 534 535def _argument_class_to_arc_type(arg_class): 536 if arg_class == 'Imm2': 537 return 'int8_t' 538 elif arg_class[:3] == 'Imm': 539 return 'int%s_t' % arg_class[3:] 540 elif arg_class == 'Cond': 541 return 'Assembler::Condition' 542 elif arg_class == 'Label': 543 return 'Assembler::Label' 544 elif sample_arc_arguments[arg_class][0] in gp_registers_32 + gp_registers_64: 545 return 'Assembler::Register' 546 elif sample_arc_arguments[arg_class][0].startswith('Assembler::st'): 547 return 'Assembler::X87Register' 548 elif sample_arc_arguments[arg_class][0].startswith('Assembler::xmm'): 549 return 'Assembler::XMMRegister' 550 else: 551 return sample_arc_arguments[arg_class][0].split('(')[0] 552 553 554if __name__ == '__main__': 555 sys.exit(main(sys.argv)) 556