diff --git a/parser_library/src/checking/instr_operand.cpp b/parser_library/src/checking/instr_operand.cpp index 0012e4ec3..65ddab681 100644 --- a/parser_library/src/checking/instr_operand.cpp +++ b/parser_library/src/checking/instr_operand.cpp @@ -212,10 +212,10 @@ hlasm_plugin::parser_library::diagnostic_op machine_operand::get_simple_operand_ return diagnostic_op::error_M111(instr_name, operand_range); case machine_operand_type::IMM: // I return diagnostic_op::error_M112(instr_name, operand_range); - case machine_operand_type::REG_IMM: // RI - return diagnostic_op::error_M113(instr_name, operand_range); case machine_operand_type::VEC_REG: // V return diagnostic_op::error_M114(instr_name, operand_range); + case machine_operand_type::RELOC_IMM: // RI + return diagnostic_op::error_M113(instr_name, operand_range); } assert(false); return diagnostic_op::error_I999(instr_name, stmt_range); @@ -265,7 +265,6 @@ one_operand::one_operand(const one_operand& op) value = op.value; is_default = op.is_default; }; - bool one_operand::check( diagnostic_op& diag, const machine_operand_format to_check, const std::string& instr_name, const range&) const { @@ -287,7 +286,6 @@ bool one_operand::check( } return true; } - // it is a simple operand if (to_check.identifier.is_signed && !is_size_corresponding_signed(value, to_check.identifier.size)) { @@ -297,7 +295,7 @@ bool one_operand::check( case machine_operand_type::IMM: diag = diagnostic_op::error_M122(instr_name, -boundary, boundary - 1, operand_range); break; - case machine_operand_type::REG_IMM: + case machine_operand_type::RELOC_IMM: diag = diagnostic_op::error_M123(instr_name, -boundary, boundary - 1, operand_range); break; default: @@ -350,10 +348,6 @@ std::string parameter::to_string() const return "M"; case machine_operand_type::REG: return "R"; - case machine_operand_type::REG_IMM: { - ret_val = "RI"; - break; - } case machine_operand_type::IMM: { ret_val = "I"; break; @@ -370,6 +364,10 @@ std::string parameter::to_string() const ret_val = "L"; break; } + case machine_operand_type::RELOC_IMM: { + ret_val = "RI"; + break; + } case machine_operand_type::VEC_REG: return "V"; case machine_operand_type::DIS_REG: diff --git a/parser_library/src/checking/instr_operand.h b/parser_library/src/checking/instr_operand.h index 08325fe7d..16d060ecc 100644 --- a/parser_library/src/checking/instr_operand.h +++ b/parser_library/src/checking/instr_operand.h @@ -67,14 +67,14 @@ enum class machine_operand_type : uint8_t { MASK, REG, - REG_IMM, IMM, NONE, DISPLC, BASE, LENGTH, VEC_REG, - DIS_REG + DIS_REG, + RELOC_IMM }; // Describes a component of machine operand format. Specifies allowed values. diff --git a/parser_library/src/context/instruction.cpp b/parser_library/src/context/instruction.cpp index 2280b1d42..c6e8a6993 100644 --- a/parser_library/src/context/instruction.cpp +++ b/parser_library/src/context/instruction.cpp @@ -346,19 +346,19 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() }, 526); - add_machine_instr(result, "BPP", mach_format::SMI, { mask_4_U, reg_imm_16_S, db_12_4_U }, 527); - add_machine_instr(result, "BPRP", mach_format::MII, { mask_4_U, reg_imm_12_S, reg_imm_24_S }, 527); - add_machine_instr(result, "BRAS", mach_format::RI_b, { reg_4_U, reg_imm_16_S }, 530); - add_machine_instr(result, "BRASL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 530); - add_machine_instr(result, "BRC", mach_format::RI_c, { mask_4_U, reg_imm_16_S }, 530); - add_machine_instr(result, "BRCL", mach_format::RIL_c, { mask_4_U, reg_imm_32_S }, 530); - add_machine_instr(result, "BRCT", mach_format::RI_b, { reg_4_U, reg_imm_16_S }, 531); - add_machine_instr(result, "BRCTG", mach_format::RI_b, { reg_4_U, reg_imm_16_S }, 531); - add_machine_instr(result, "BRCTH", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 531); - add_machine_instr(result, "BRXH", mach_format::RSI, { reg_4_U, reg_4_U, reg_imm_16_S }, 532); - add_machine_instr(result, "BRXHG", mach_format::RIE_e, { reg_4_U, reg_4_U, reg_imm_16_S }, 532); - add_machine_instr(result, "BRXLE", mach_format::RSI, { reg_4_U, reg_4_U, reg_imm_16_S }, 532); - add_machine_instr(result, "BRXLG", mach_format::RIE_e, { reg_4_U, reg_4_U, reg_imm_16_S }, 532); + add_machine_instr(result, "BPP", mach_format::SMI, { mask_4_U, rel_addr_imm_16_S, db_12_4_U }, 527); + add_machine_instr(result, "BPRP", mach_format::MII, { mask_4_U, rel_addr_imm_12_S, rel_addr_imm_24_S }, 527); + add_machine_instr(result, "BRAS", mach_format::RI_b, { reg_4_U, rel_addr_imm_16_S }, 530); + add_machine_instr(result, "BRASL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 530); + add_machine_instr(result, "BRC", mach_format::RI_c, { mask_4_U, rel_addr_imm_16_S }, 530); + add_machine_instr(result, "BRCL", mach_format::RIL_c, { mask_4_U, rel_addr_imm_32_S }, 530); + add_machine_instr(result, "BRCT", mach_format::RI_b, { reg_4_U, rel_addr_imm_16_S }, 531); + add_machine_instr(result, "BRCTG", mach_format::RI_b, { reg_4_U, rel_addr_imm_16_S }, 531); + add_machine_instr(result, "BRCTH", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 531); + add_machine_instr(result, "BRXH", mach_format::RSI, { reg_4_U, reg_4_U, rel_addr_imm_16_S }, 532); + add_machine_instr(result, "BRXHG", mach_format::RIE_e, { reg_4_U, reg_4_U, rel_addr_imm_16_S }, 532); + add_machine_instr(result, "BRXLE", mach_format::RSI, { reg_4_U, reg_4_U, rel_addr_imm_16_S }, 532); + add_machine_instr(result, "BRXLG", mach_format::RIE_e, { reg_4_U, reg_4_U, rel_addr_imm_16_S }, 532); add_machine_instr(result, "CKSM", mach_format::RRE, { reg_4_U, reg_4_U }, 533); add_machine_instr(result, "KM", mach_format::RRE, { reg_4_U, reg_4_U }, 537); add_machine_instr(result, "KMC", mach_format::RRE, { reg_4_U, reg_4_U }, 537); @@ -375,13 +375,13 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "CGF", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 618); add_machine_instr(result, "CFI", mach_format::RIL_a, { reg_4_U, imm_32_S }, 618); add_machine_instr(result, "CGFI", mach_format::RIL_a, { reg_4_U, imm_32_S }, 619); - add_machine_instr(result, "CRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 619); - add_machine_instr(result, "CGRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 619); - add_machine_instr(result, "CGFRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 619); + add_machine_instr(result, "CRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 619); + add_machine_instr(result, "CGRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 619); + add_machine_instr(result, "CGFRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 619); add_machine_instr(result, "CRB", mach_format::RRS, { reg_4_U, reg_4_U, mask_4_U, db_12_4_U }, 619); add_machine_instr(result, "CGRB", mach_format::RRS, { reg_4_U, reg_4_U, mask_4_U, db_12_4_U }, 619); - add_machine_instr(result, "CRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, reg_imm_16_S }, 619); - add_machine_instr(result, "CGRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, reg_imm_16_S }, 620); + add_machine_instr(result, "CRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, rel_addr_imm_16_S }, 619); + add_machine_instr(result, "CGRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, rel_addr_imm_16_S }, 620); add_machine_instr(result, "CIB", mach_format::RIS, @@ -404,8 +404,8 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() }, 620); - add_machine_instr(result, "CIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, reg_imm_16_S }, 620); - add_machine_instr(result, "CGIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, reg_imm_16_S }, 620); + add_machine_instr(result, "CIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, rel_addr_imm_16_S }, 620); + add_machine_instr(result, "CGIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, rel_addr_imm_16_S }, 620); add_machine_instr(result, "CFC", mach_format::S, { db_12_4_U }, 621); add_machine_instr(result, "CS", mach_format::RS_a, { reg_4_U, reg_4_U, db_12_4_U }, 628); add_machine_instr(result, "CSY", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 628); @@ -426,8 +426,8 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "CHHSI", mach_format::SIL, { db_12_4_U, imm_16_S }, 634); add_machine_instr(result, "CHSI", mach_format::SIL, { db_12_4_U, imm_16_S }, 634); add_machine_instr(result, "CGHSI", mach_format::SIL, { db_12_4_U, imm_16_S }, 634); - add_machine_instr(result, "CHRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 634); - add_machine_instr(result, "CGHRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 634); + add_machine_instr(result, "CHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 634); + add_machine_instr(result, "CGHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 634); add_machine_instr(result, "CHHR", mach_format::RRE, { reg_4_U, reg_4_U }, 635); add_machine_instr(result, "CHLR", mach_format::RRE, { reg_4_U, reg_4_U }, 635); add_machine_instr(result, "CHF", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 635); @@ -455,19 +455,19 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "CLFHSI", mach_format::SIL, { db_12_4_U, imm_16_U }, 636); add_machine_instr(result, "CLGHSI", mach_format::SIL, { db_12_4_U, imm_16_U }, 636); add_machine_instr(result, "CLHHSI", mach_format::SIL, { db_12_4_U, imm_16_U }, 636); - add_machine_instr(result, "CLRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 637); - add_machine_instr(result, "CLGRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 637); - add_machine_instr(result, "CLGFRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 637); - add_machine_instr(result, "CLHRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 637); - add_machine_instr(result, "CLGHRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 637); + add_machine_instr(result, "CLRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 637); + add_machine_instr(result, "CLGRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 637); + add_machine_instr(result, "CLGFRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 637); + add_machine_instr(result, "CLHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 637); + add_machine_instr(result, "CLGHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 637); add_machine_instr(result, "CLRB", mach_format::RRS, { reg_4_U, reg_4_U, mask_4_U, db_12_4_U }, 638); add_machine_instr(result, "CLGRB", mach_format::RRS, { reg_4_U, reg_4_U, mask_4_U, db_12_4_U }, 638); - add_machine_instr(result, "CLRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, reg_imm_16_S }, 638); - add_machine_instr(result, "CLGRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, reg_imm_16_S }, 638); + add_machine_instr(result, "CLRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, rel_addr_imm_16_S }, 638); + add_machine_instr(result, "CLGRJ", mach_format::RIE_b, { reg_4_U, reg_4_U, mask_4_U, rel_addr_imm_16_S }, 638); add_machine_instr(result, "CLIB", mach_format::RIS, { reg_4_U, imm_8_S, mask_4_U, db_12_4_U }, 638); add_machine_instr(result, "CLGIB", mach_format::RIS, { reg_4_U, imm_8_S, mask_4_U, db_12_4_U }, 638); - add_machine_instr(result, "CLIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, reg_imm_16_S }, 638); - add_machine_instr(result, "CLGIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, reg_imm_16_S }, 638); + add_machine_instr(result, "CLIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, rel_addr_imm_16_S }, 638); + add_machine_instr(result, "CLGIJ", mach_format::RIE_c, { reg_4_U, imm_8_S, mask_4_U, rel_addr_imm_16_S }, 638); add_machine_instr(result, "CLRT", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 639); add_machine_instr(result, "CLGRT", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 639); add_machine_instr(result, "CLT", mach_format::RSY_b, { reg_4_U, mask_4_U, dxb_20_4x4_S }, 639); @@ -540,7 +540,7 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "EX", mach_format::RX_a, { reg_4_U, dxb_12_4x4_U }, 740); add_machine_instr(result, "XIHF", mach_format::RIL_a, { reg_4_U, imm_32_S }, 740); add_machine_instr(result, "XILF", mach_format::RIL_a, { reg_4_U, imm_32_S }, 740); - add_machine_instr(result, "EXRL", mach_format::RIL_b, { reg_4_U, imm_32_S }, 740); + add_machine_instr(result, "EXRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 740); add_machine_instr(result, "EAR", mach_format::RRE, { reg_4_U, reg_4_U }, 741); add_machine_instr(result, "ECAG", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 741); add_machine_instr(result, "ECTG", mach_format::SSF, { db_12_4_U, db_12_4_U, reg_4_U }, 744); @@ -567,16 +567,16 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "LG", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 748); add_machine_instr(result, "LGF", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 748); add_machine_instr(result, "LGFI", mach_format::RIL_a, { reg_4_U, imm_32_S }, 748); - add_machine_instr(result, "LRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 748); - add_machine_instr(result, "LGRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 748); - add_machine_instr(result, "LGFRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 748); + add_machine_instr(result, "LRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 748); + add_machine_instr(result, "LGRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 748); + add_machine_instr(result, "LGFRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 748); add_machine_instr(result, "LAM", mach_format::RS_a, { reg_4_U, reg_4_U, db_12_4_U }, 749); add_machine_instr(result, "LAMY", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 749); add_machine_instr(result, "LA", mach_format::RX_a, { reg_4_U, dxb_12_4x4_U }, 750); add_machine_instr(result, "LAY", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 750); add_machine_instr(result, "LAE", mach_format::RX_a, { reg_4_U, dxb_12_4x4_U }, 750); add_machine_instr(result, "LAEY", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 750); - add_machine_instr(result, "LARL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 751); + add_machine_instr(result, "LARL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 751); add_machine_instr(result, "LAA", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 752); add_machine_instr(result, "LAAG", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 752); add_machine_instr(result, "LAAL", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 752); @@ -616,8 +616,8 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "LGH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 760); add_machine_instr(result, "LHI", mach_format::RI_a, { reg_4_U, imm_16_S }, 760); add_machine_instr(result, "LGHI", mach_format::RI_a, { reg_4_U, imm_16_S }, 760); - add_machine_instr(result, "LHRL", mach_format::RIL_b, { reg_4_U, imm_32_S }, 760); - add_machine_instr(result, "LGHRL", mach_format::RIL_b, { reg_4_U, imm_32_S }, 760); + add_machine_instr(result, "LHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 760); + add_machine_instr(result, "LGHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 760); add_machine_instr(result, "LHH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 761); add_machine_instr(result, "LOCHI", mach_format::RIE_g, { reg_4_U, imm_16_S, mask_4_U }, 761); add_machine_instr(result, "LOCGHI", mach_format::RIE_g, { reg_4_U, imm_16_S, mask_4_U }, 761); @@ -626,7 +626,7 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "LFHAT", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 762); add_machine_instr(result, "LLGFR", mach_format::RRE, { reg_4_U, reg_4_U }, 762); add_machine_instr(result, "LLGF", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 762); - add_machine_instr(result, "LLGFRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 762); + add_machine_instr(result, "LLGFRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 762); add_machine_instr(result, "LLGFAT", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 763); add_machine_instr(result, "LLCR", mach_format::RRE, { reg_4_U, reg_4_U }, 763); add_machine_instr(result, "LLGCR", mach_format::RRE, { reg_4_U, reg_4_U }, 763); @@ -638,8 +638,8 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "LLGHR", mach_format::RRE, { reg_4_U, reg_4_U }, 764); add_machine_instr(result, "LLH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 764); add_machine_instr(result, "LLGH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 764); - add_machine_instr(result, "LLHRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 764); - add_machine_instr(result, "LLGHRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 764); + add_machine_instr(result, "LLHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 764); + add_machine_instr(result, "LLGHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 764); add_machine_instr(result, "LLHH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 765); add_machine_instr(result, "LLIHF", mach_format::RIL_a, { reg_4_U, imm_32_S }, 765); add_machine_instr(result, "LLIHH", mach_format::RI_a, { reg_4_U, imm_16_S }, 765); @@ -756,7 +756,7 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "PPNO", mach_format::RRE, { reg_4_U, reg_4_U }, 830); add_machine_instr(result, "POPCNT", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 1, 853); add_machine_instr(result, "PFD", mach_format::RXY_b, { mask_4_U, dxb_20_4x4_S }, 843); - add_machine_instr(result, "PFDRL", mach_format::RIL_c, { mask_4_U, reg_imm_32_S }, 843); + add_machine_instr(result, "PFDRL", mach_format::RIL_c, { mask_4_U, rel_addr_imm_32_S }, 843); add_machine_instr(result, "RLL", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 845); add_machine_instr(result, "RLLG", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 845); add_machine_instr(result, "RNSBG", mach_format::RIE_f, { reg_4_U, reg_4_U, imm_8_S, imm_8_S, imm_8_S }, 1, 845); @@ -799,8 +799,8 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "ST", mach_format::RX_a, { reg_4_U, dxb_12_4x4_U }, 860); add_machine_instr(result, "STY", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 861); add_machine_instr(result, "STG", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 861); - add_machine_instr(result, "STRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 861); - add_machine_instr(result, "STGRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 861); + add_machine_instr(result, "STRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 861); + add_machine_instr(result, "STGRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 861); add_machine_instr(result, "STAM", mach_format::RS_a, { reg_4_U, reg_4_U, db_12_4_U }, 861); add_machine_instr(result, "STAMY", mach_format::RSY_a, { reg_4_U, reg_4_U, db_20_4_S }, 861); add_machine_instr(result, "STC", mach_format::RX_a, { reg_4_U, dxb_12_4x4_U }, 862); @@ -816,7 +816,7 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions() add_machine_instr(result, "STGSC", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 867); add_machine_instr(result, "STH", mach_format::RX_a, { reg_4_U, dxb_12_4x4_U }, 867); add_machine_instr(result, "STHY", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 868); - add_machine_instr(result, "STHRL", mach_format::RIL_b, { reg_4_U, reg_imm_32_S }, 868); + add_machine_instr(result, "STHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 868); add_machine_instr(result, "STHH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 868); add_machine_instr(result, "STFH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 868); add_machine_instr(result, "STM", mach_format::RS_a, { reg_4_U, reg_4_U, db_12_4_U }, 869); diff --git a/parser_library/src/context/instruction.h b/parser_library/src/context/instruction.h index 1038b973e..13df5e24c 100644 --- a/parser_library/src/context/instruction.h +++ b/parser_library/src/context/instruction.h @@ -136,10 +136,10 @@ const checking::parameter imm_24s = { true, 24, checking::machine_operand_type:: const checking::parameter imm_32s = { true, 32, checking::machine_operand_type::IMM }; const checking::parameter imm_32u = { false, 32, checking::machine_operand_type::IMM }; const checking::parameter vec_reg = { false, 4, checking::machine_operand_type::VEC_REG }; -const checking::parameter reg_imm_12s = { true, 12, checking::machine_operand_type::REG_IMM }; -const checking::parameter reg_imm_16s = { true, 16, checking::machine_operand_type::REG_IMM }; -const checking::parameter reg_imm_24s = { true, 24, checking::machine_operand_type::REG_IMM }; -const checking::parameter reg_imm_32s = { true, 32, checking::machine_operand_type::REG_IMM }; +const checking::parameter reladdr_imm_12s = { true, 12, checking::machine_operand_type::RELOC_IMM }; +const checking::parameter reladdr_imm_16s = { true, 16, checking::machine_operand_type::RELOC_IMM }; +const checking::parameter reladdr_imm_24s = { true, 24, checking::machine_operand_type::RELOC_IMM }; +const checking::parameter reladdr_imm_32s = { true, 32, checking::machine_operand_type::RELOC_IMM }; /* Rules for displacement operands: @@ -169,10 +169,15 @@ const checking::machine_operand_format imm_32_U = checking::machine_operand_form const checking::machine_operand_format vec_reg_4_U = checking::machine_operand_format(vec_reg, empty, empty); const checking::machine_operand_format db_12_8x4L_U = checking::machine_operand_format(dis_12u, length_8, base_); const checking::machine_operand_format db_12_4x4L_U = checking::machine_operand_format(dis_12u, length_4, base_); -const checking::machine_operand_format reg_imm_12_S = checking::machine_operand_format(reg_imm_12s, empty, empty); -const checking::machine_operand_format reg_imm_16_S = checking::machine_operand_format(reg_imm_16s, empty, empty); -const checking::machine_operand_format reg_imm_24_S = checking::machine_operand_format(reg_imm_24s, empty, empty); -const checking::machine_operand_format reg_imm_32_S = checking::machine_operand_format(reg_imm_32s, empty, empty); +const checking::machine_operand_format rel_addr_imm_12_S = + checking::machine_operand_format(reladdr_imm_12s, empty, empty); +const checking::machine_operand_format rel_addr_imm_16_S = + checking::machine_operand_format(reladdr_imm_16s, empty, empty); +const checking::machine_operand_format rel_addr_imm_24_S = + checking::machine_operand_format(reladdr_imm_24s, empty, empty); +const checking::machine_operand_format rel_addr_imm_32_S = + checking::machine_operand_format(reladdr_imm_32s, empty, empty); + // machine instruction representation for checking class machine_instruction diff --git a/parser_library/src/diagnostic.cpp b/parser_library/src/diagnostic.cpp index 55c5c4fd0..84f06a5ce 100644 --- a/parser_library/src/diagnostic.cpp +++ b/parser_library/src/diagnostic.cpp @@ -1231,7 +1231,7 @@ diagnostic_op diagnostic_op::error_M113(const std::string& instr_name, const ran { return diagnostic_op(diagnostic_severity::error, "M113", - "Error at " + instr_name + " instruction: operand must be an absolute register immediate value", + "Error at " + instr_name + " instruction: operand must be relocatable symbol or an absolute immediate value", range); } @@ -1272,7 +1272,7 @@ diagnostic_op diagnostic_op::error_M123(const std::string& instr_name, long long { return diagnostic_op(diagnostic_severity::error, "M123", - "Error at " + instr_name + " instruction: register immediate operand absolute value must be between " + "Error at " + instr_name + " instruction: relocatable symbol or immediate absolute value must be between " + std::to_string(from) + " and " + std::to_string(to), range); } @@ -1477,6 +1477,13 @@ diagnostic_op diagnostic_op::warn_D025(const range& range, const std::string& ty return diagnostic_op( diagnostic_severity::warning, "D025", "The " + modifier + " modifier is ignored with type " + type, range); } +diagnostic_op diagnostic_op::warn_D031(const range& range, const std::string& operand_value) +{ + return diagnostic_op(diagnostic_severity::warning, + "D031", + "Using absolute value '" + operand_value + "' as relative immediate value", + range); +} diagnostic_op diagnostic_op::error_D026(const range& range) { @@ -1857,6 +1864,11 @@ diagnostic_op diagnostic_op::error_ME002(const range& range) return diagnostic_op(diagnostic_severity::error, "ME002", "multiplication or division of address", range); } +diagnostic_op diagnostic_op::error_ME003(const range& range) +{ + return diagnostic_op( + diagnostic_severity::error, "ME003", "Relative Immediate operand must evaluate into an even offset.", range); +} diagnostic_op diagnostic_op::error_CE001(const range& range) { return diagnostic_op(diagnostic_severity::error, "CE001", "Operator expected", range); diff --git a/parser_library/src/diagnostic.h b/parser_library/src/diagnostic.h index ddafc4b6b..6d84148bb 100644 --- a/parser_library/src/diagnostic.h +++ b/parser_library/src/diagnostic.h @@ -444,6 +444,7 @@ struct diagnostic_op static diagnostic_op error_D028(const range& range); static diagnostic_op error_D029(const range& range); static diagnostic_op error_D030(const range& range, const std::string& type); + static diagnostic_op warn_D031(const range& range, const std::string& modifier); static diagnostic_op error_M102(const std::string& instr_name, const range& range); @@ -591,6 +592,8 @@ struct diagnostic_op static diagnostic_op error_ME002(const range& range); + static diagnostic_op error_ME003(const range& range); + static diagnostic_op error_CE001(const range& range); static diagnostic_op error_CE002(const std::string& message, const range& range); diff --git a/parser_library/src/expressions/mach_operator.h b/parser_library/src/expressions/mach_operator.h index 688c66858..71c4c2fe7 100644 --- a/parser_library/src/expressions/mach_operator.h +++ b/parser_library/src/expressions/mach_operator.h @@ -107,7 +107,12 @@ struct sub static std::string sign_char_begin() { return "-"; } static std::string sign_char_end() { return ""; } }; - +struct rel_addr +{ + static std::string sign_char() { return "-"; } + static std::string sign_char_begin() { return "-"; } + static std::string sign_char_end() { return ""; } +}; struct mul { static std::string sign_char() { return "*"; } @@ -137,7 +142,21 @@ inline mach_expression::value_t mach_expr_binary::evaluate(mach_evaluate_in { return left_->evaluate(info) - right_->evaluate(info); } +template<> +inline mach_expression::value_t mach_expr_binary::evaluate(mach_evaluate_info info) const +{ + auto location = left_->evaluate(info); + auto target = right_->evaluate(info); + if (target.value_kind() == context::symbol_value_kind::ABS) + { + add_diagnostic(diagnostic_op::warn_D031(get_range(), std::to_string(target.get_abs()))); + return target; + } + if ((target - location).value_kind() == context::symbol_value_kind::ABS && (target - location).get_abs() % 2 != 0) + add_diagnostic(diagnostic_op::error_ME003(get_range())); + return target - location; +} template<> inline mach_expression::value_t mach_expr_binary::evaluate(mach_evaluate_info info) const { @@ -198,7 +217,11 @@ inline context::dependency_collector mach_expr_binary::get_dependencies(mac { return left_->get_dependencies(info) - right_->get_dependencies(info); } - +template<> +inline context::dependency_collector mach_expr_binary::get_dependencies(mach_evaluate_info info) const +{ + return left_->get_dependencies(info) - right_->get_dependencies(info); +} template<> inline context::dependency_collector mach_expr_binary::get_dependencies(mach_evaluate_info info) const { diff --git a/parser_library/src/parsing/parser_impl.cpp b/parser_library/src/parsing/parser_impl.cpp index 3ef4ce042..59f3fd537 100644 --- a/parser_library/src/parsing/parser_impl.cpp +++ b/parser_library/src/parsing/parser_impl.cpp @@ -160,6 +160,7 @@ statement_fields_parser::parse_result parser_impl::parse_operand_field(std::stri break; case processing::processing_form::MACH: line = std::move(h.parser->op_rem_body_mach_r()->line); + transform_imm_reg_operands(line.operands, opcode.value); break; case processing::processing_form::DAT: line = std::move(h.parser->op_rem_body_dat_r()->line); @@ -533,6 +534,44 @@ void parser_impl::process_lookahead() parse_lookahead_operands(std::move(*look_lab_instr->op_text), look_lab_instr->op_range); } } +void parser_impl::transform_imm_reg_operands(semantics::operand_list& op_list, id_index instruction) +{ + if (instruction->empty()) + return; + const machine_instruction* instr; + std::vector> replaced; + if (auto mnem_tmp = context::instruction::mnemonic_codes.find(*instruction); + mnem_tmp != context::instruction::mnemonic_codes.end()) + { + const auto& mnemonic = context::instruction::mnemonic_codes.at(*instruction); + instr = mnemonic.instruction; + replaced = mnemonic.replaced; + } + else + { + instr = &context::instruction::machine_instructions.at(*instruction); + } + int position = 0; + for (const auto& operand : op_list) + { + for (const auto& [index, value] : replaced) + { + if (index == position) + { + position++; + } + } + if (auto type = instr->operands[position].identifier.type; type == checking::machine_operand_type::RELOC_IMM + && operand.get()->access_mach() != nullptr && operand.get()->access_mach()->kind == mach_kind::EXPR) + { + auto range = operand.get()->access_mach()->access_expr()->expression.get()->get_range(); + mach_expr_ptr& transformed_exp = operand.get()->access_mach()->access_expr()->expression; + transformed_exp = std::make_unique>( + std::make_unique(range), std::move(transformed_exp), range); + } + position++; + } +} void parser_impl::parse_operands(const std::string& text, range text_range) { @@ -592,6 +631,7 @@ void parser_impl::parse_operands(const std::string& text, range text_range) break; case processing::processing_form::MACH: h.parser->op_rem_body_mach(); + transform_imm_reg_operands(h.parser->collector.current_operands().value, opcode.value); break; case processing::processing_form::DAT: h.parser->op_rem_body_dat(); diff --git a/parser_library/src/parsing/parser_impl.h b/parser_library/src/parsing/parser_impl.h index 3bb57ca81..a483df58c 100644 --- a/parser_library/src/parsing/parser_impl.h +++ b/parser_library/src/parsing/parser_impl.h @@ -140,7 +140,7 @@ class parser_impl : public antlr4::Parser, void parse_operands(const std::string& text, range text_range); void parse_lookahead_operands(const std::string& text, range text_range); - + static void transform_imm_reg_operands(semantics::operand_list& op_list, context::id_index instruction); antlr4::misc::IntervalSet getExpectedTokens() override; bool input_tokens_invalidated = false; diff --git a/parser_library/src/semantics/collector.cpp b/parser_library/src/semantics/collector.cpp index 93116190c..2312c635a 100644 --- a/parser_library/src/semantics/collector.cpp +++ b/parser_library/src/semantics/collector.cpp @@ -36,7 +36,9 @@ const instruction_si& collector::current_instruction() { return *instr_; } bool collector::has_instruction() const { return instr_.has_value(); } -const operands_si& collector::current_operands() { return *op_; } + +const operands_si& collector::current_operands() const { return *op_; } +operands_si& collector::current_operands() { return *op_; } const remarks_si& collector::current_remarks() { return *rem_; } diff --git a/parser_library/src/semantics/collector.h b/parser_library/src/semantics/collector.h index d3edc855d..12e4ce9ea 100644 --- a/parser_library/src/semantics/collector.h +++ b/parser_library/src/semantics/collector.h @@ -34,7 +34,8 @@ class collector bool has_label() const; const instruction_si& current_instruction(); bool has_instruction() const; - const operands_si& current_operands(); + const operands_si& current_operands() const; + operands_si& current_operands(); const remarks_si& current_remarks(); void set_label_field(range symbol_range); diff --git a/parser_library/src/semantics/operand_impls.cpp b/parser_library/src/semantics/operand_impls.cpp index 0916b244d..34e3c92c1 100644 --- a/parser_library/src/semantics/operand_impls.cpp +++ b/parser_library/src/semantics/operand_impls.cpp @@ -81,9 +81,8 @@ address_machine_operand* machine_operand::access_address() return kind == mach_kind::ADDR ? static_cast(this) : nullptr; } -std::unique_ptr make_check_operand(expressions::mach_evaluate_info info, - const expressions::mach_expression& expr, - std::optional type_hint = std::nullopt) +std::unique_ptr make_check_operand( + expressions::mach_evaluate_info info, const expressions::mach_expression& expr) { auto res = expr.evaluate(info); if (res.value_kind() == context::symbol_value_kind::ABS) @@ -92,18 +91,24 @@ std::unique_ptr make_check_operand(expressions::mach_evaluate } else { - if (type_hint && *type_hint == checking::machine_operand_type::REG_IMM) - { - return std::make_unique(0); - } - else - { - return std::make_unique( - checking::address_state::UNRES, 0, 0, 0, checking::operand_state::ONE_OP); - } + return std::make_unique( + checking::address_state::UNRES, 0, 0, 0, checking::operand_state::ONE_OP); + } +} +std::unique_ptr make_rel_imm_operand( + expressions::mach_evaluate_info info, const expressions::mach_expression& expr) +{ + auto res = expr.evaluate(info); + if (res.value_kind() == context::symbol_value_kind::ABS) + { + return std::make_unique(std::to_string(res.get_abs()), res.get_abs()); + } + else + { + return std::make_unique( + checking::address_state::UNRES, 0, 0, 0, checking::operand_state::ONE_OP); } } - //***************** expr_machine_operand ********************* expr_machine_operand::expr_machine_operand(expressions::mach_expr_ptr expression, range operand_range) @@ -120,7 +125,11 @@ std::unique_ptr expr_machine_operand::get_operand_value(expre std::unique_ptr expr_machine_operand::get_operand_value( expressions::mach_evaluate_info info, checking::machine_operand_type type_hint) const { - return make_check_operand(info, *expression, type_hint); + if (type_hint == checking::machine_operand_type::RELOC_IMM) + { + return make_rel_imm_operand(info, *expression); + } + return make_check_operand(info, *expression); } // suppress MSVC warning 'inherits via dominance' diff --git a/parser_library/test/checking/mach_instr_diag_test.cpp b/parser_library/test/checking/mach_instr_diag_test.cpp index fb2f413b1..eaac50621 100644 --- a/parser_library/test/checking/mach_instr_diag_test.cpp +++ b/parser_library/test/checking/mach_instr_diag_test.cpp @@ -224,11 +224,13 @@ TEST(diagnostics, immS_out_of_range) ASSERT_EQ(a.diags().at(0).code, "M122"); } -TEST(diagnostics, regImmS_out_of_range) +TEST(diagnostics, reloc_ImmS_out_of_range) { std::string input( R"( - BPRP 1,2333,3 + BRAS 1,DISP +LEN123 DS CL(64444) +DISP MVC 0(1),1 )"); analyzer a(input); a.analyze(); @@ -307,12 +309,11 @@ TEST(diagnostics, imm_expected) ASSERT_EQ(a.diags().size(), (size_t)1); ASSERT_EQ(a.diags().at(0).code, "M112"); } - -TEST(diagnostics, regImm_expected) +TEST(diagnostics, relocImm_expected) { std::string input( R"( - BPP 1,2(2,2),111 + EXRL 1,0(1) )"); analyzer a(input); a.analyze(); @@ -322,6 +323,55 @@ TEST(diagnostics, regImm_expected) ASSERT_EQ(a.diags().at(0).code, "M113"); } +TEST(diagnostics, invalid_reloc_operand) +{ + std::string input( + R"( +SIZE EQU 5 + EXRL 1,LENGTH+LENGTH +LENGTH DS CL(SIZE) +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + + ASSERT_EQ(a.diags().size(), (size_t)1); + ASSERT_EQ(a.diags().at(0).code, "M113"); +} + +TEST(diagnostics, valid_reloc_operand) +{ + std::string input( + R"( +SIZE EQU 5 + EXRL 1,LENGTH+4 +LENGTH DS CL(SIZE) +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + + ASSERT_EQ(a.diags().size(), (size_t)0); +} + +TEST(diagnostics, reloc_operand_halfword_o_error) +{ + std::string input( + R"( + EXRL 1,LEN120 +LENGTH DS CL(5) +LEN120 DS CL1 +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + + ASSERT_EQ(a.diags().size(), (size_t)1); + ASSERT_EQ(a.diags().at(0).code, "ME003"); +} TEST(diagnostics, vecReg_expected) { std::string input( @@ -334,4 +384,116 @@ TEST(diagnostics, vecReg_expected) ASSERT_EQ(a.parser().getNumberOfSyntaxErrors(), (size_t)0); ASSERT_EQ(a.diags().size(), (size_t)1); ASSERT_EQ(a.diags().at(0).code, "M114"); +} +TEST(diagnostics, relocSymbol_expected) +{ + std::string input( + R"( + EXRL 1,12 +)"); + analyzer a(input); + a.analyze(); + a.collect_diags(); + ASSERT_EQ(a.diags().size(), (size_t)1); + ASSERT_EQ(a.diags().at(0).code, "D031"); +} +TEST(diagnostics, setc_variable_mnemonic_reloc_operand) +{ + std::string input( + R"( +&RRR SETC 'NAME' + J &RRR +&RRR DS 0H +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + ASSERT_EQ(a.parser().getNumberOfSyntaxErrors(), (size_t)0); + ASSERT_EQ(a.diags().size(), (size_t)0); +} +TEST(diagnostics, setc_variable_reloc_operand) +{ + std::string input( + R"( +TEST CSECT +&OPS SETC '0,TEST' + LARL &OPS + END TEST +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + ASSERT_EQ(a.parser().getNumberOfSyntaxErrors(), (size_t)0); + ASSERT_EQ(a.diags().size(), (size_t)0); +} +TEST(diagnostics, setc_variable_reloc_symbol_expected_warn) +{ + std::string input( + R"( +TEST CSECT +&OPS SETC '0,1' + LARL &OPS + END TEST +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + ASSERT_EQ(a.diags().size(), (size_t)1); + ASSERT_EQ(a.diags().at(0).code, "D031"); +} +TEST(diagnostics, reloc_parsed_in_macro_valid) +{ + std::string input( + R"( + MACRO + CALLRIOPERAND +LABEL BRAS 0,*+12 + MEND + CALLRIOPERAND +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + ASSERT_EQ(a.parser().getNumberOfSyntaxErrors(), (size_t)0); + ASSERT_EQ(a.diags().size(), (size_t)0); +} +TEST(diagnostics, reloc_parsed_in_macro_with_immValue) +{ + std::string input( + R"( + MACRO + CALLRIOPERAND +LABEL BRAS 0,12 + MEND + CALLRIOPERAND +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + ASSERT_EQ(a.diags().size(), (size_t)1); + ASSERT_EQ(a.diags().at(0).code, "D031"); +} +TEST(diagnostics, reloc_parsed_in_macro_alignment_error) +{ + std::string input( + R"( + MACRO + CALLRIOPERAND + EXRL 1,LEN120 +LENGTH DS CL(5) +LEN120 DS CL1 + MEND + CALLRIOPERAND +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + ASSERT_EQ(a.diags().size(), (size_t)1); + ASSERT_EQ(a.diags().at(0).code, "ME003"); } \ No newline at end of file diff --git a/parser_library/test/diagnostics_check_test.cpp b/parser_library/test/diagnostics_check_test.cpp index 207157cbc..103f374f1 100644 --- a/parser_library/test/diagnostics_check_test.cpp +++ b/parser_library/test/diagnostics_check_test.cpp @@ -21,13 +21,14 @@ TEST(diagnostics, overall_correctness) { std::string input( R"( - J 5 + J LABEL ACONTROL COMPAT(CASE) CATTR DEFLOAD,FILL(3) CATTR FILL(3) AINSERT ' sam64',BACK &x setc ' sam64' AINSERT '&x',BACK +LABEL EQU *+2 )"); analyzer a(input); a.analyze(); @@ -189,44 +190,46 @@ TEST(diagnostics, mnemonics) R"( B 10(2,2) BR 4 - J 30000 + J LABEL1 NOP 10(2,2) NOPR 4 - JNOP 30000 + JNOP LABEL1 BH 10(2,2) BHR 4 - JH 30000 + JH LABEL1 BL 10(2,2) BLR 4 - JL 30000 + JL LABEL1 BE 10(2,2) BER 4 - JE 30000 + JE LABEL1 BNH 10(2,2) BNHR 4 - JNH 30000 + JNH LABEL1 BNL 10(2,2) BNLR 4 - JNL 30000 + JNL LABEL1 BNE 10(2,2) BNER 4 - JNE 30000 + JNE LABEL1 BO 10(2,2) BOR 4 - JO 30000 + JO LABEL1 BNO 10(2,2) BNOR 4 - JNO 30000 - BRUL 80000 - BRHL 80000 - BRLL 80000 - BREL 80000 - BRNHL 80000 - BRNLL 80000 - BRNEL 80000 - BROL 80000 - BRNOL 80000 - JLNOP 80000 + JNO LABEL1 + BRUL LABEL2 + BRHL LABEL2 + BRLL LABEL2 + BREL LABEL2 + BRNHL LABEL2 + BRNLL LABEL2 + BRNEL LABEL2 + BROL LABEL2 + BRNOL LABEL2 + JLNOP LABEL2 +LABEL1 EQU *+19000 +LABEL2 equ *+79000 )"); analyzer a(input);