From 5c9cd0146dceb6552d7a5a592b374ce07ae50585 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 14 Jun 2026 21:57:27 +0100 Subject: [PATCH] Add `@(require_results)` to operand procedures --- core/rexcode/arm32/operands.odin | 14 ++++++++ core/rexcode/arm64/operands.odin | 33 +++++++++++++++++-- core/rexcode/mips/operands.odin | 16 +++++++++ core/rexcode/mos6502/operands.odin | 50 ++++++++++++++++------------- core/rexcode/mos65816/operands.odin | 49 +++++++++++++++------------- core/rexcode/ppc/operands.odin | 7 ++++ core/rexcode/ppc_vle/operands.odin | 7 ++++ core/rexcode/riscv/operands.odin | 8 +++++ core/rexcode/rsp/operands.odin | 8 +++++ core/rexcode/x86/operands.odin | 1 + 10 files changed, 147 insertions(+), 46 deletions(-) diff --git a/core/rexcode/arm32/operands.odin b/core/rexcode/arm32/operands.odin index 4f215c78f..d7405d843 100644 --- a/core/rexcode/arm32/operands.odin +++ b/core/rexcode/arm32/operands.odin @@ -66,18 +66,23 @@ Memory :: struct #packed { } #assert(size_of(Memory) == 12) +@(require_results) mem_imm :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, disp = disp, sign = 1, mode = .OFFSET} } +@(require_results) mem_imm_pre :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, disp = disp, sign = 1, mode = .PRE_INDEX} } +@(require_results) mem_imm_post :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, disp = disp, sign = 1, mode = .POST_INDEX} } +@(require_results) mem_reg :: #force_inline proc "contextless" (base, index: Register, sign: i8 = 1) -> Memory { return Memory{base = base, index = index, sign = sign, mode = .OFFSET} } +@(require_results) mem_reg_shift :: #force_inline proc "contextless" ( base, index: Register, st: Shift_Type, amt: u8, sign: i8 = 1, ) -> Memory { @@ -106,32 +111,41 @@ Operand :: struct #packed { // ---- Operand builders ------------------------------------------------------ +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 4, cond = 14} } +@(require_results) op_reg_shifted :: #force_inline proc "contextless" ( r: Register, st: Shift_Type, amt: u8, ) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 4, shift_type = st, shift_amt = amt, cond = 14} } +@(require_results) op_imm :: #force_inline proc "contextless" (v: i64, size: u8 = 4) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = size, cond = 14} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { return Operand{mem = m, kind = .MEMORY, size = 4, cond = 14} } +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32, size: u8 = 4) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE, size = size, cond = 14} } +@(require_results) op_rel_offset :: #force_inline proc "contextless" (off: i64) -> Operand { return Operand{relative = off, kind = .RELATIVE, size = 4, cond = 14} } +@(require_results) op_reg_list :: #force_inline proc "contextless" (mask: u16) -> Operand { return Operand{immediate = i64(mask), kind = .REG_LIST, size = 2, cond = 14} } +@(require_results) op_dpr_lane :: #force_inline proc "contextless" (d: Register, idx: u8) -> Operand { return Operand{reg = d, kind = .REGISTER, size = 4, lane = idx, cond = 14} } +@(require_results) op_qpr_lane :: #force_inline proc "contextless" (q: Register, idx: u8) -> Operand { return Operand{reg = q, kind = .REGISTER, size = 4, lane = idx, cond = 14} } diff --git a/core/rexcode/arm64/operands.odin b/core/rexcode/arm64/operands.odin index f03ce1af9..5a27ef79a 100644 --- a/core/rexcode/arm64/operands.odin +++ b/core/rexcode/arm64/operands.odin @@ -110,27 +110,39 @@ Operand :: struct #packed { // Constructors -- generic // ----------------------------------------------------------------------------- -op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 4} } -op_imm :: #force_inline proc "contextless" (v: i64, size: u8 = 4) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = size} } +@(require_results) +op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { + return Operand{reg = r, kind = .REGISTER, size = 4} +} +@(require_results) +op_imm :: #force_inline proc "contextless" (v: i64, size: u8 = 4) -> Operand { + return Operand{immediate = v, kind = .IMMEDIATE, size = size} +} +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32, size: u8 = 4) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE, size = size} } +@(require_results) op_rel_offset :: #force_inline proc "contextless" (off: i64) -> Operand { return Operand{relative = off, kind = .RELATIVE, size = 4} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { return Operand{mem = m, kind = .MEMORY, size = 4} } +@(require_results) op_shifted :: #force_inline proc "contextless" (r: Register, type: Shift_Type, amount: u8) -> Operand { return Operand{shifted = Shifted_Reg{reg = r, type = type, amount = amount}, kind = .SHIFTED_REG, size = 4} } +@(require_results) op_extended :: #force_inline proc "contextless" (r: Register, ext: Extend, amount: u8) -> Operand { return Operand{extended = Extended_Reg{reg = r, extend = ext, amount = amount}, kind = .EXTENDED_REG, size = 4} } +@(require_results) op_cond :: #force_inline proc "contextless" (c: Cond) -> Operand { return Operand{cond = u8(c), kind = .COND, size = 1} } @@ -141,15 +153,19 @@ op_cond :: #force_inline proc "contextless" (c: Cond) -> Operand { // table form when multiple element sizes share a base mnemonic. // ----------------------------------------------------------------------------- +@(require_results) op_z_b :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_Z | u16(n & 0x1F)), kind = .REGISTER, size = 1} } +@(require_results) op_z_h :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_Z | u16(n & 0x1F)), kind = .REGISTER, size = 2} } +@(require_results) op_z_s :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_Z | u16(n & 0x1F)), kind = .REGISTER, size = 4} } +@(require_results) op_z_d :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_Z | u16(n & 0x1F)), kind = .REGISTER, size = 8} } @@ -164,27 +180,35 @@ op_z_d :: #force_inline proc "contextless" (n: u8) -> Operand { // to inspect.) // ----------------------------------------------------------------------------- +@(require_results) op_v_8b :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 8} } +@(require_results) op_v_16b :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 16} } +@(require_results) op_v_4h :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 24} } +@(require_results) op_v_8h :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 32} } +@(require_results) op_v_2s :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 40} } +@(require_results) op_v_4s :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 48} } +@(require_results) op_v_1d :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 56} } +@(require_results) op_v_2d :: #force_inline proc "contextless" (n: u8) -> Operand { return Operand{reg = Register(REG_V | u16(n & 0x1F)), kind = .REGISTER, size = 64} } @@ -193,18 +217,23 @@ op_v_2d :: #force_inline proc "contextless" (n: u8) -> Operand { // Memory constructors (one per addressing mode) // ----------------------------------------------------------------------------- +@(require_results) mem_offset :: #force_inline proc "contextless" (base: Register, disp: i32 = 0) -> Memory { return Memory{base = base, index = NONE, disp = disp, mode = .OFFSET} } +@(require_results) mem_pre :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, index = NONE, disp = disp, mode = .PRE_INDEXED} } +@(require_results) mem_post :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, index = NONE, disp = disp, mode = .POST_INDEXED} } +@(require_results) mem_reg :: #force_inline proc "contextless" (base, index: Register, shift_amount: u8 = 0) -> Memory { return Memory{base = base, index = index, mode = .REG_OFFSET, shift = shift_amount, extend = .UXTX} } +@(require_results) mem_ext :: #force_inline proc "contextless" (base, index: Register, ext: Extend, shift_amount: u8 = 0) -> Memory { return Memory{base = base, index = index, mode = .EXT_REG_OFFSET, extend = ext, shift = shift_amount} } diff --git a/core/rexcode/mips/operands.odin b/core/rexcode/mips/operands.odin index d7a81d70a..3a1c741d7 100644 --- a/core/rexcode/mips/operands.odin +++ b/core/rexcode/mips/operands.odin @@ -28,6 +28,7 @@ Memory :: struct #packed { } #assert(size_of(Memory) == 8) +@(require_results) mem :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, disp = disp} } @@ -35,14 +36,18 @@ mem :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { // Convenience aliases that mirror x86's naming convention so cross-arch // helper code reads the same. mem_base_disp :: mem + +@(require_results) mem_base_only :: #force_inline proc "contextless" (base: Register) -> Memory { return Memory{base = base, disp = 0} } +@(require_results) mem_base :: #force_inline proc "contextless" (m: Memory) -> Register { return m.base } +@(require_results) mem_disp :: #force_inline proc "contextless" (m: Memory) -> i32 { return m.disp } @@ -65,29 +70,35 @@ Operand :: struct #packed { // Generic operand constructors // ----------------------------------------------------------------------------- +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 4} } +@(require_results) op_reg_sized :: #force_inline proc "contextless" (r: Register, size: u8) -> Operand { return Operand{reg = r, kind = .REGISTER, size = size} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory, size: u8) -> Operand { return Operand{mem = m, kind = .MEMORY, size = size} } +@(require_results) op_imm :: #force_inline proc "contextless" (v: i64, size: u8) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = size} } // Branch/jump target operand. `label_id` indexes a Label_Definition // array (resolved by the encoder during pass 2 -- same model as x86). +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE, size = 4} } // Raw offset (skip label resolution). +@(require_results) op_rel_offset :: #force_inline proc "contextless" (offset: i64) -> Operand { return Operand{relative = offset, kind = .RELATIVE, size = 4} } @@ -96,22 +107,27 @@ op_rel_offset :: #force_inline proc "contextless" (offset: i64) -> Operand { // Typed register operand constructors (compile-time class safety) // ----------------------------------------------------------------------------- +@(require_results) op_gpr :: #force_inline proc "contextless" (g: GPR) -> Operand { return Operand{reg = Register(REG_GPR | u16(g)), kind = .REGISTER, size = 4} } +@(require_results) op_fpr :: #force_inline proc "contextless" (f: FPR) -> Operand { return Operand{reg = Register(REG_FPR | u16(f)), kind = .REGISTER, size = 4} } +@(require_results) op_cp0 :: #force_inline proc "contextless" (c: CP0_Reg) -> Operand { return Operand{reg = Register(REG_CP0 | u16(c)), kind = .REGISTER, size = 4} } +@(require_results) op_gte_data :: #force_inline proc "contextless" (r: GTE_DataReg) -> Operand { return Operand{reg = Register(REG_CP2D | u16(r)), kind = .REGISTER, size = 4} } +@(require_results) op_gte_ctrl :: #force_inline proc "contextless" (r: GTE_CtrlReg) -> Operand { return Operand{reg = Register(REG_CP2C | u16(r)), kind = .REGISTER, size = 4} } diff --git a/core/rexcode/mos6502/operands.odin b/core/rexcode/mos6502/operands.odin index 8323c8f6f..76e130d0a 100644 --- a/core/rexcode/mos6502/operands.odin +++ b/core/rexcode/mos6502/operands.odin @@ -56,17 +56,17 @@ Memory :: struct #packed { // Memory constructors (one per addressing mode) // ----------------------------------------------------------------------------- -mem_zp :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .ZP } } -mem_zp_x :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .ZP_X } } -mem_zp_y :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .ZP_Y } } -mem_abs :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .ABS } } -mem_abs_x :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .ABS_X } } -mem_abs_y :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .ABS_Y } } -mem_ind :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .IND } } -mem_ind_x :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .IND_X } } -mem_ind_y :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .IND_Y } } -mem_ind_zp :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .IND_ZP } } -mem_ind_abs_x :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .IND_ABS_X } } +@(require_results) mem_zp :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .ZP } } +@(require_results) mem_zp_x :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .ZP_X } } +@(require_results) mem_zp_y :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .ZP_Y } } +@(require_results) mem_abs :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .ABS } } +@(require_results) mem_abs_x :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .ABS_X } } +@(require_results) mem_abs_y :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .ABS_Y } } +@(require_results) mem_ind :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .IND } } +@(require_results) mem_ind_x :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .IND_X } } +@(require_results) mem_ind_y :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .IND_Y } } +@(require_results) mem_ind_zp :: #force_inline proc "contextless" (addr: u8) -> Memory { return Memory{address = u16(addr), mode = .IND_ZP } } +@(require_results) mem_ind_abs_x :: #force_inline proc "contextless" (addr: u16) -> Memory { return Memory{address = addr, mode = .IND_ABS_X } } // ----------------------------------------------------------------------------- // Operand: kind-tagged union, 16 bytes @@ -87,18 +87,22 @@ Operand :: struct #packed { // Generic constructors ------------------------------------------------------- +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 1} } +@(require_results) op_imm8 :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = 1} } +@(require_results) op_imm16 :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = 2} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { size: u8 = 2 switch m.mode { @@ -110,23 +114,25 @@ op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { return Operand{mem = m, kind = .MEMORY, size = size} } +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32, size: u8 = 1) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE, size = size} } +@(require_results) op_rel_offset :: #force_inline proc "contextless" (offset: i64) -> Operand { return Operand{relative = offset, kind = .RELATIVE, size = 1} } // Address-mode-named operand helpers (call site reads like asm). -op_zp :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_zp(a)) } -op_zp_x :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_zp_x(a)) } -op_zp_y :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_zp_y(a)) } -op_abs :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_abs(a)) } -op_abs_x :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_abs_x(a)) } -op_abs_y :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_abs_y(a)) } -op_ind :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_ind(a)) } -op_ind_x :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_ind_x(a)) } -op_ind_y :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_ind_y(a)) } -op_ind_zp :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_ind_zp(a)) } -op_ind_abs_x :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_ind_abs_x(a)) } +@(require_results) op_zp :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_zp(a)) } +@(require_results) op_zp_x :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_zp_x(a)) } +@(require_results) op_zp_y :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_zp_y(a)) } +@(require_results) op_abs :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_abs(a)) } +@(require_results) op_abs_x :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_abs_x(a)) } +@(require_results) op_abs_y :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_abs_y(a)) } +@(require_results) op_ind :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_ind(a)) } +@(require_results) op_ind_x :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_ind_x(a)) } +@(require_results) op_ind_y :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_ind_y(a)) } +@(require_results) op_ind_zp :: #force_inline proc "contextless" (a: u8) -> Operand { return op_mem(mem_ind_zp(a)) } +@(require_results) op_ind_abs_x :: #force_inline proc "contextless" (a: u16) -> Operand { return op_mem(mem_ind_abs_x(a)) } diff --git a/core/rexcode/mos65816/operands.odin b/core/rexcode/mos65816/operands.odin index 612c6ee50..a8d7c34af 100644 --- a/core/rexcode/mos65816/operands.odin +++ b/core/rexcode/mos65816/operands.odin @@ -60,24 +60,24 @@ Memory :: bit_field u32 { } #assert(size_of(Memory) == 4) -mem_dp :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP } } -mem_dp_x :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_X } } -mem_dp_y :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_Y } } -mem_dp_ind :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND } } -mem_dp_ind_x :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_X } } -mem_dp_ind_y :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_Y } } -mem_dp_ind_long :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_LONG } } -mem_dp_ind_long_y:: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_LONG_Y } } -mem_abs :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS } } -mem_abs_x :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_X } } -mem_abs_y :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_Y } } -mem_abs_ind :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_IND } } -mem_abs_ind_long :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_IND_LONG } } -mem_abs_ind_x :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_IND_X } } -mem_long :: #force_inline proc "contextless" (a: u32) -> Memory { return Memory{address = a & 0xFFFFFF, mode = .LONG } } -mem_long_x :: #force_inline proc "contextless" (a: u32) -> Memory { return Memory{address = a & 0xFFFFFF, mode = .LONG_X } } -mem_sr :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .SR } } -mem_sr_ind_y :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .SR_IND_Y } } +@(require_results) mem_dp :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP } } +@(require_results) mem_dp_x :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_X } } +@(require_results) mem_dp_y :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_Y } } +@(require_results) mem_dp_ind :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND } } +@(require_results) mem_dp_ind_x :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_X } } +@(require_results) mem_dp_ind_y :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_Y } } +@(require_results) mem_dp_ind_long :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_LONG } } +@(require_results) mem_dp_ind_long_y:: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .DP_IND_LONG_Y } } +@(require_results) mem_abs :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS } } +@(require_results) mem_abs_x :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_X } } +@(require_results) mem_abs_y :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_Y } } +@(require_results) mem_abs_ind :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_IND } } +@(require_results) mem_abs_ind_long :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_IND_LONG } } +@(require_results) mem_abs_ind_x :: #force_inline proc "contextless" (a: u16) -> Memory { return Memory{address = u32(a), mode = .ABS_IND_X } } +@(require_results) mem_long :: #force_inline proc "contextless" (a: u32) -> Memory { return Memory{address = a & 0xFFFFFF, mode = .LONG } } +@(require_results) mem_long_x :: #force_inline proc "contextless" (a: u32) -> Memory { return Memory{address = a & 0xFFFFFF, mode = .LONG_X } } +@(require_results) mem_sr :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .SR } } +@(require_results) mem_sr_ind_y :: #force_inline proc "contextless" (a: u8) -> Memory { return Memory{address = u32(a), mode = .SR_IND_Y } } Operand :: struct #packed { using _: struct #raw_union { @@ -92,10 +92,12 @@ Operand :: struct #packed { } #assert(size_of(Operand) == 16) -op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 1} } -op_imm8 :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = 1} } -op_imm16 :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = 2} } -op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 1} } +@(require_results) op_imm8 :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = 1} } +@(require_results) op_imm16 :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = 2} } + +@(require_results) +op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { // Operand size = width of the address literal as encoded. size: u8 = 2 switch m.mode { @@ -110,9 +112,12 @@ op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { return Operand{mem = m, kind = .MEMORY, size = size} } +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32, size: u8 = 1) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE, size = size} } + +@(require_results) op_rel_offset :: #force_inline proc "contextless" (off: i64) -> Operand { return Operand{relative = off, kind = .RELATIVE, size = 1} } diff --git a/core/rexcode/ppc/operands.odin b/core/rexcode/ppc/operands.odin index 81a4437d2..e9c91f4df 100644 --- a/core/rexcode/ppc/operands.odin +++ b/core/rexcode/ppc/operands.odin @@ -34,9 +34,11 @@ Memory :: struct #packed { } #assert(size_of(Memory) == 12) +@(require_results) mem_d :: #force_inline proc "contextless" (base: Register, disp: i64) -> Memory { return Memory{base = base, index = NONE, disp = disp} } +@(require_results) mem_x :: #force_inline proc "contextless" (base, index: Register) -> Memory { return Memory{base = base, index = index, disp = 0} } @@ -54,18 +56,23 @@ Operand :: struct #packed { } // raw_union size = max(2, 12, 8, 8) = 12; + 1 kind + 1 size + 2 pad = 16 bytes +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER} } +@(require_results) op_imm :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { return Operand{mem = m, kind = .MEMORY} } +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE} } +@(require_results) op_rel_offset :: #force_inline proc "contextless" (off: i64) -> Operand { return Operand{relative = off, kind = .RELATIVE} } diff --git a/core/rexcode/ppc_vle/operands.odin b/core/rexcode/ppc_vle/operands.odin index 01ea56ae2..a130c6c47 100644 --- a/core/rexcode/ppc_vle/operands.odin +++ b/core/rexcode/ppc_vle/operands.odin @@ -19,9 +19,11 @@ Memory :: struct #packed { } #assert(size_of(Memory) == 12) +@(require_results) mem_d :: #force_inline proc "contextless" (base: Register, disp: i64) -> Memory { return Memory{base = base, index = NONE, disp = disp} } +@(require_results) mem_x :: #force_inline proc "contextless" (base, index: Register) -> Memory { return Memory{base = base, index = index, disp = 0} } @@ -38,18 +40,23 @@ Operand :: struct #packed { _: [2]u8, } +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER} } +@(require_results) op_imm :: #force_inline proc "contextless" (v: i64) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { return Operand{mem = m, kind = .MEMORY} } +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE} } +@(require_results) op_rel_offset :: #force_inline proc "contextless" (off: i64) -> Operand { return Operand{relative = off, kind = .RELATIVE} } diff --git a/core/rexcode/riscv/operands.odin b/core/rexcode/riscv/operands.odin index 1d4ed4ee2..7959540f1 100644 --- a/core/rexcode/riscv/operands.odin +++ b/core/rexcode/riscv/operands.odin @@ -28,6 +28,7 @@ Memory :: struct #packed { } #assert(size_of(Memory) == 8) +@(require_results) mem :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, disp = disp} } @@ -45,20 +46,27 @@ Operand :: struct #packed { } #assert(size_of(Operand) == 16) +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 4} } +@(require_results) op_imm :: #force_inline proc "contextless" (v: i64, size: u8) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = size} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory) -> Operand { return Operand{mem = m, kind = .MEMORY, size = 4} } +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32, size: u8 = 2) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE, size = size} } +@(require_results) op_rel_offset :: #force_inline proc "contextless" (off: i64) -> Operand { return Operand{relative = off, kind = .RELATIVE, size = 2} } // Typed constructors +@(require_results) op_gpr :: #force_inline proc "contextless" (g: GPR) -> Operand { return Operand{reg = Register(REG_GPR | u16(g)), kind = .REGISTER, size = 4} } +@(require_results) op_fpr :: #force_inline proc "contextless" (f: FPR) -> Operand { return Operand{reg = Register(REG_FPR | u16(f)), kind = .REGISTER, size = 4} } diff --git a/core/rexcode/rsp/operands.odin b/core/rexcode/rsp/operands.odin index 7351d717d..59e693eb0 100644 --- a/core/rexcode/rsp/operands.odin +++ b/core/rexcode/rsp/operands.odin @@ -34,10 +34,12 @@ Vector_Mem :: struct #packed { } #assert(size_of(Vector_Mem) == 8) +@(require_results) mem :: #force_inline proc "contextless" (base: Register, disp: i32) -> Memory { return Memory{base = base, disp = disp} } +@(require_results) vmem :: #force_inline proc "contextless" (base: Register, element: u8, offset: i32) -> Vector_Mem { return Vector_Mem{base = base, element = element, offset = offset} } @@ -58,26 +60,32 @@ Operand :: struct #packed { } #assert(size_of(Operand) == 16) +@(require_results) op_reg :: #force_inline proc "contextless" (r: Register) -> Operand { return Operand{reg = r, kind = .REGISTER, size = 4} } +@(require_results) op_vr :: #force_inline proc "contextless" (r: Register, element: u8 = 0) -> Operand { return Operand{reg = r, kind = .VECTOR_REG, size = 16, element = element} } +@(require_results) op_mem :: #force_inline proc "contextless" (m: Memory, size: u8) -> Operand { return Operand{mem = m, kind = .MEMORY, size = size} } +@(require_results) op_vmem :: #force_inline proc "contextless" (m: Vector_Mem, size: u8) -> Operand { return Operand{vmem = m, kind = .VECTOR_MEM, size = size} } +@(require_results) op_imm :: #force_inline proc "contextless" (v: i64, size: u8) -> Operand { return Operand{immediate = v, kind = .IMMEDIATE, size = size} } +@(require_results) op_label :: #force_inline proc "contextless" (label_id: u32) -> Operand { return Operand{relative = i64(label_id), kind = .RELATIVE, size = 4} } diff --git a/core/rexcode/x86/operands.odin b/core/rexcode/x86/operands.odin index cfbd6881d..85e8e60f4 100644 --- a/core/rexcode/x86/operands.odin +++ b/core/rexcode/x86/operands.odin @@ -37,6 +37,7 @@ Memory :: bit_field u64 { index_class: u8 | 5, } +@(require_results) mem_make :: proc "contextless" (base: Register, index: Register, scale: u8, disp: i32, segment: Register) -> Memory { mem: Memory = --- mem.base_hw = MEM_BASE_NONE