+static void
+learn_parse_load_immediate(const char *s, struct learn_spec *spec)
+{
+ const char *full_s = s;
+ const char *arrow = strstr(s, "->");
+ struct mf_subfield dst;
+ union mf_subvalue imm;
+
+ memset(&imm, 0, sizeof imm);
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && arrow) {
+ const char *in = arrow - 1;
+ uint8_t *out = imm.u8 + sizeof imm.u8 - 1;
+ int n = arrow - (s + 2);
+ int i;
+
+ for (i = 0; i < n; i++) {
+ int hexit = hexit_value(in[-i]);
+ if (hexit < 0) {
+ ovs_fatal(0, "%s: bad hex digit in value", full_s);
+ }
+ out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit;
+ }
+ s = arrow;
+ } else {
+ imm.be64[1] = htonll(strtoull(s, (char **) &s, 0));
+ }
+
+ if (strncmp(s, "->", 2)) {
+ ovs_fatal(0, "%s: missing `->' following value", full_s);
+ }
+ s += 2;
+
+ s = mf_parse_subfield(&dst, s);
+ if (*s != '\0') {
+ ovs_fatal(0, "%s: trailing garbage following destination", full_s);
+ }
+
+ if (!bitwise_is_all_zeros(&imm, sizeof imm, dst.n_bits,
+ (8 * sizeof imm) - dst.n_bits)) {
+ ovs_fatal(0, "%s: value does not fit into %u bits",
+ full_s, dst.n_bits);
+ }
+
+ spec->n_bits = dst.n_bits;
+ spec->src_type = NX_LEARN_SRC_IMMEDIATE;
+ spec->src_imm = imm;
+ spec->dst_type = NX_LEARN_DST_LOAD;
+ spec->dst = dst;
+}
+